/// <summary> /// Creates a new Discord RPC Client which can be used to send Rich Presence and receive Join / Spectate events. This constructor exposes more advance features such as custom NamedPipeClients and Loggers. /// </summary> /// <param name="applicationID">The ID of the application created at discord's developers portal.</param> /// <param name="pipe">The pipe to connect too. If -1, then the client will scan for the first available instance of Discord.</param> /// <param name="logger">The logger used to report messages. If null, then a <see cref="NullLogger"/> will be created and logs will be ignored.</param> /// <param name="autoEvents">Should events be automatically invoked from the RPC Thread as they arrive from discord?</param> /// <param name="client">The pipe client to use and communicate to discord through. If null, the default <see cref="ManagedNamedPipeClient"/> will be used.</param> public DiscordRpcClient(string applicationID, int pipe = -1, ILogger logger = null, bool autoEvents = true, INamedPipeClient client = null) { //Make sure appID is NOT null. if (string.IsNullOrEmpty(applicationID)) { throw new ArgumentNullException("applicationID"); } //Ensure we actually have json ahead of time. If statement is pointless, but its there just to ensure there is no unused warnings. var jsonConverterType = typeof(Newtonsoft.Json.JsonConverter); if (jsonConverterType == null) { throw new Exception("JsonConverter Type Not Found"); } //Store the properties ApplicationID = applicationID.Trim(); TargetPipe = pipe; ProcessID = System.Diagnostics.Process.GetCurrentProcess().Id; HasRegisteredUriScheme = false; AutoEvents = autoEvents; SkipIdenticalPresence = true; //Validate the process id if (ProcessID < 10) { throw new InvalidOperationException("Process ID must be greater than 10."); } //Prepare the logger _logger = logger ?? new NullLogger(); //Create the RPC client, giving it the important details connection = new RpcConnection(ApplicationID, ProcessID, TargetPipe, client ?? new ManagedNamedPipeClient(), autoEvents ? 0 : 128U) { ShutdownOnly = _shutdownOnly, Logger = _logger }; //Subscribe to its event connection.OnRpcMessage += (sender, msg) => { if (OnRpcMessage != null) { OnRpcMessage.Invoke(this, msg); } if (AutoEvents) { ProcessMessage(msg); } }; }
/// <summary> /// Adds a message to the message queue. Does not copy the message, so besure to copy it yourself or dereference it. /// </summary> /// <param name="message">The message to add</param> private void EnqueueMessage(IMessage message) { //Invoke the message try { if (OnRpcMessage != null) { OnRpcMessage.Invoke(this, message); } } catch (Exception e) { Logger.Error("Unhandled Exception while processing event: {0}", e.GetType().FullName); Logger.Error(e.Message); Logger.Error(e.StackTrace); } //Small queue sizes should just ignore messages if (_maxRxQueueSize <= 0) { Logger.Trace("Enqueued Message, but queue size is 0."); return; } //Large queue sizes should keep the queue in check Logger.Trace("Enqueue Message: " + message.Type); lock (l_rxqueue) { //If we are too big drop the last element if (_rxqueue.Count == _maxRxQueueSize) { Logger.Warning("Too many enqueued messages, dropping oldest one."); _rxqueue.Dequeue(); } //Enqueue the message _rxqueue.Enqueue(message); } }