예제 #1
0
        public async Task DisconnectAsync()
        {
            await ButtplugFFI.SendDisconnect(_messageSorter, _clientHandle, SorterCallbackDelegate, GCHandle.ToIntPtr(_indexHandle));

            _devices.Clear();
            Connected = false;
        }
예제 #2
0
        public async Task DisconnectAsync()
        {
            await ButtplugFFI.SendDisconnect(_messageSorter, _clientHandle);

            _devices.Clear();
            Connected = false;
        }
        public async Task ConnectAsync(ButtplugWebsocketConnectorOptions aConnector)
        {
            await ButtplugFFI.SendConnectWebsocket(_messageSorter, _clientHandle, aConnector.NetworkAddress.ToString(), false, _sorterCallbackDelegate, GCHandle.ToIntPtr(_indexHandle))
            .ConfigureAwait(false);

            Connected = true;
        }
예제 #4
0
        protected ButtplugClient(string aClientName, ButtplugCallback aCallback)
        {
            Name = aClientName;
            SorterCallbackDelegate = aCallback;
            var context     = new WeakReference(this);
            var clientIndex = _clientCounter;

            // Since we can pass the handle, I don't *think* this needs to be pinned?
            _indexHandle = GCHandle.Alloc(clientIndex);
            _clientStorage.Add(_clientCounter, context);
            _clientHandle = ButtplugFFI.SendCreateClient(aClientName, SorterCallbackDelegate, GCHandle.ToIntPtr(_indexHandle));
        }
예제 #5
0
 public async Task ConnectAsync(ButtplugEmbeddedConnectorOptions aConnector)
 {
     if (aConnector == null)
     {
         aConnector = new ButtplugEmbeddedConnectorOptions();
     }
     await ButtplugFFI.SendConnectLocal(
         _messageSorter,
         _clientHandle,
         aConnector.ServerName,
         aConnector.MaxPingTime,
         aConnector.AllowRawMessages,
         aConnector.DeviceConfigJSON,
         aConnector.UserDeviceConfigJSON,
         aConnector.DeviceCommunicationManagerTypes);
 }
        protected ButtplugClient(string aClientName, ButtplugCallback aCallback)
        {
            Name = aClientName;
            _sorterCallbackDelegate = aCallback;
            _disposeLock            = new object();

            _messageSorter = new ButtplugFFIMessageSorter();
            _devices       = new Dictionary <uint, ButtplugClientDevice>();

            var context     = new WeakReference(this);
            var clientIndex = _clientCounter;

            _clientCounter += 1;

            // Since we can pass the handle, I don't *think* this needs to be pinned?
            _indexHandle = GCHandle.Alloc(clientIndex);
            _clientStorage.Add(clientIndex, context);
            _clientHandle = ButtplugFFI.SendCreateClient(aClientName, _sorterCallbackDelegate, GCHandle.ToIntPtr(_indexHandle));
        }
예제 #7
0
        public async Task ConnectAsync(ButtplugEmbeddedConnectorOptions aConnector)
        {
            if (aConnector == null)
            {
                aConnector = new ButtplugEmbeddedConnectorOptions();
            }

            await ButtplugFFI.SendConnectLocal(
                _messageSorter,
                _clientHandle,
                aConnector.ServerName,
                aConnector.MaxPingTime,
                aConnector.AllowRawMessages,
                aConnector.DeviceConfigJSON,
                aConnector.UserDeviceConfigJSON,
                aConnector.DeviceCommunicationManagerTypes,
                SorterCallbackDelegate, GCHandle.ToIntPtr(_indexHandle));

            Connected = true;
        }
예제 #8
0
        public async Task ConnectAsync(ButtplugWebsocketConnectorOptions aConnector)
        {
            await ButtplugFFI.SendConnectWebsocket(_messageSorter, _clientHandle, aConnector.NetworkAddress.ToString(), false);

            Connected = true;
        }
예제 #9
0
 public Task SendVibrateCmd(Dictionary <uint, double> aCmds)
 {
     return(ButtplugFFI.SendVibrateCmd(Sorter, Handle, Index, aCmds));
 }
예제 #10
0
 public ButtplugClient(string aClientName)
 {
     Name = aClientName;
     SorterCallbackDelegate = SorterCallback;
     _clientHandle          = ButtplugFFI.SendCreateClient(aClientName, SorterCallbackDelegate);
 }
예제 #11
0
 public async Task StopScanningAsync()
 {
     IsScanning = false;
     await ButtplugFFI.SendStopScanning(_messageSorter, _clientHandle);
 }
예제 #12
0
 public async Task StopAllDevicesAsync()
 {
     await ButtplugFFI.SendStopAllDevices(_messageSorter, _clientHandle);
 }
예제 #13
0
 public async Task PingAsync()
 {
     await ButtplugFFI.SendPing(_messageSorter, _clientHandle);
 }
예제 #14
0
        public void SorterCallback(UIntPtr buf, int buf_length)
        {
            Span <byte> byteArray;

            unsafe
            {
                byteArray = new Span <byte>(buf.ToPointer(), buf_length);
            }
            var server_message = ButtplugFFIServerMessage.Parser.ParseFrom(byteArray.ToArray());

            if (server_message.Id > 0)
            {
                _messageSorter.CheckMessage(server_message);
            }
            else if (server_message.Message.MsgCase == ButtplugFFIServerMessage.Types.FFIMessage.MsgOneofCase.ServerMessage)
            {
                if (server_message.Message.ServerMessage.MsgCase == ServerMessage.MsgOneofCase.DeviceAdded)
                {
                    var device_added_message = server_message.Message.ServerMessage.DeviceAdded;
                    var device_handle        = ButtplugFFI.SendCreateDevice(_clientHandle, device_added_message.Index);
                    var attribute_dict       = new Dictionary <ServerMessage.Types.MessageAttributeType, ButtplugMessageAttributes>();
                    for (var i = 0; i < device_added_message.MessageAttributes.Count; ++i)
                    {
                        var attributes = device_added_message.MessageAttributes[i];
                        var device_message_attributes = new ButtplugMessageAttributes(attributes.FeatureCount, attributes.StepCount.ToArray(),
                                                                                      attributes.Endpoints.ToArray(), attributes.MaxDuration.ToArray(), null, null);
                        attribute_dict.Add(attributes.MessageType, device_message_attributes);
                    }
                    var device = new ButtplugClientDevice(_messageSorter, device_handle, device_added_message.Index, device_added_message.Name, attribute_dict);
                    _devices.Add(device_added_message.Index, device);
                    DeviceAdded.Invoke(this, new DeviceAddedEventArgs(device));
                }
                else if (server_message.Message.ServerMessage.MsgCase == ServerMessage.MsgOneofCase.DeviceRemoved)
                {
                    var device_removed_message = server_message.Message.ServerMessage.DeviceRemoved;
                    var device = _devices[device_removed_message.Index];
                    _devices.Remove(device_removed_message.Index);
                    DeviceRemoved.Invoke(this, new DeviceRemovedEventArgs(device));
                }
                else if (server_message.Message.ServerMessage.MsgCase == ServerMessage.MsgOneofCase.Disconnect)
                {
                    Connected = false;
                    ServerDisconnect?.Invoke(this, null);
                }
                else if (server_message.Message.ServerMessage.MsgCase == ServerMessage.MsgOneofCase.Error)
                {
                    var errorMsg = server_message.Message.ServerMessage.Error;
                    var error    = ButtplugException.FromError(errorMsg);
                    if (error is ButtplugPingException)
                    {
                        PingTimeout?.Invoke(this, null);
                    }
                    ErrorReceived?.Invoke(this, new ButtplugExceptionEventArgs(error));
                }
                else if (server_message.Message.ServerMessage.MsgCase == ServerMessage.MsgOneofCase.ScanningFinished)
                {
                    ScanningFinished?.Invoke(this, null);
                }
                else
                {
                    // We should probably do something here with unhandled events, but I'm not particularly sure what. I miss pattern matching. :(
                }
            }
            else
            {
                // We should probably do something here with unhandled events, but I'm not particularly sure what. I miss pattern matching. :(
            }
        }
예제 #15
0
 public async Task StartScanningAsync()
 {
     await ButtplugFFI.SendStartScanning(_messageSorter, _clientHandle);
 }
 public Task SendVibrateCmd(Dictionary <uint, double> aCmds)
 {
     return(ButtplugFFI.SendVibrateCmd(_sorter, _handle, Index, aCmds, _sorterCallback, _sorterCallbackCtx));
 }
예제 #17
0
 public static void ActivateEnvLogger()
 {
     ButtplugFFI.ActivateEnvLogger();
 }
예제 #18
0
 public async Task StartScanningAsync()
 {
     IsScanning = true;
     await ButtplugFFI.SendStartScanning(_messageSorter, _clientHandle, _sorterCallbackDelegate, GCHandle.ToIntPtr(_indexHandle))
     .ConfigureAwait(false);
 }
예제 #19
0
        protected void SorterCallbackHandler(IntPtr buf, int buf_length)
        {
            // Process the data BEFORE we throw to the C# executor, otherwise
            // Rust will clean up the memory and we'll have nothing to read
            // from, meaning a null message at best and a crash at worst.
            Span <byte> byteArray;

            unsafe
            {
                byteArray = new Span <byte>(buf.ToPointer(), buf_length);
            }
            var server_message = ButtplugFFIServerMessage.Parser.ParseFrom(byteArray.ToArray());

            // Run the response in the context of the C# executor, not the Rust
            // thread. This means that if something goes wrong we at least
            // aren't blocking a rust executor thread.
            Task.Run(() =>
            {
                if (server_message.Id > 0)
                {
                    _messageSorter.CheckMessage(server_message);
                }
                else if (server_message.Message.MsgCase == ButtplugFFIServerMessage.Types.FFIMessage.MsgOneofCase.ServerMessage)
                {
                    if (server_message.Message.ServerMessage.MsgCase == ServerMessage.MsgOneofCase.DeviceAdded)
                    {
                        var device_added_message = server_message.Message.ServerMessage.DeviceAdded;
                        if (_devices.ContainsKey(device_added_message.Index))
                        {
                            ErrorReceived?.Invoke(this, new ButtplugExceptionEventArgs(new ButtplugDeviceException("A duplicate device index was received. This is most likely a bug, please file at https://github.com/buttplugio/b******g-rs-ffi")));
                            return;
                        }
                        var device_handle  = ButtplugFFI.SendCreateDevice(_clientHandle, device_added_message.Index);
                        var attribute_dict = new Dictionary <ServerMessage.Types.MessageAttributeType, ButtplugMessageAttributes>();
                        for (var i = 0; i < device_added_message.MessageAttributes.Count; ++i)
                        {
                            var attributes = device_added_message.MessageAttributes[i];
                            var device_message_attributes = new ButtplugMessageAttributes(attributes.FeatureCount, attributes.StepCount.ToArray(),
                                                                                          attributes.Endpoints.ToArray(), attributes.MaxDuration.ToArray(), null, null);
                            attribute_dict.Add(attributes.MessageType, device_message_attributes);
                        }
                        var device = new ButtplugClientDevice(_messageSorter, device_handle, device_added_message.Index, device_added_message.Name, attribute_dict, SorterCallbackDelegate, GCHandle.ToIntPtr(_indexHandle));
                        _devices.Add(device_added_message.Index, device);
                        DeviceAdded?.Invoke(this, new DeviceAddedEventArgs(device));
                    }
                    else if (server_message.Message.ServerMessage.MsgCase == ServerMessage.MsgOneofCase.DeviceRemoved)
                    {
                        var device_removed_message = server_message.Message.ServerMessage.DeviceRemoved;
                        if (!_devices.ContainsKey(device_removed_message.Index))
                        {
                            // Device was removed from our dict before we could remove it ourselves.
                            return;
                        }
                        try
                        {
                            var device = _devices[device_removed_message.Index];
                            _devices.Remove(device_removed_message.Index);
                            DeviceRemoved?.Invoke(this, new DeviceRemovedEventArgs(device));
                        }
                        catch (KeyNotFoundException)
                        {
                            ErrorReceived?.Invoke(this, new ButtplugExceptionEventArgs(new ButtplugDeviceException($"Cannot remove device index {device_removed_message.Index}, device not found.")));
                        }
                    }
                    else if (server_message.Message.ServerMessage.MsgCase == ServerMessage.MsgOneofCase.Disconnect)
                    {
                        Connected = false;
                        _devices.Clear();
                        ServerDisconnect?.Invoke(this, null);
                    }
                    else if (server_message.Message.ServerMessage.MsgCase == ServerMessage.MsgOneofCase.Error)
                    {
                        var errorMsg = server_message.Message.ServerMessage.Error;
                        var error    = ButtplugException.FromError(errorMsg);
                        if (error is ButtplugPingException)
                        {
                            PingTimeout?.Invoke(this, null);
                        }
                        ErrorReceived?.Invoke(this, new ButtplugExceptionEventArgs(error));
                    }
                    else if (server_message.Message.ServerMessage.MsgCase == ServerMessage.MsgOneofCase.ScanningFinished)
                    {
                        IsScanning = false;
                        ScanningFinished?.Invoke(this, null);
                    }
                    else
                    {
                        // We should probably do something here with unhandled events, but I'm not particularly sure what. I miss pattern matching. :(
                    }
                }
                else
                {
                    // We should probably do something here with unhandled events, but I'm not particularly sure what. I miss pattern matching. :(
                }
            });
        }
예제 #20
0
 public async Task PingAsync()
 {
     await ButtplugFFI.SendPing(_messageSorter, _clientHandle, SorterCallbackDelegate, GCHandle.ToIntPtr(_indexHandle));
 }
예제 #21
0
 public async Task StopAllDevicesAsync()
 {
     await ButtplugFFI.SendStopAllDevices(_messageSorter, _clientHandle, SorterCallbackDelegate, GCHandle.ToIntPtr(_indexHandle));
 }
예제 #22
0
 public async Task StopScanningAsync()
 {
     IsScanning = false;
     await ButtplugFFI.SendStopScanning(_messageSorter, _clientHandle, SorterCallbackDelegate, GCHandle.ToIntPtr(_indexHandle));
 }