private void EmulatorOnInputReportReceived(object o, InputReportReceivedEventArgs args) { foreach (var plugin in SinkPlugins.Select(p => p.Value)) { plugin.InputReportReceived(args.Device, args.Report); } }
public void Start() { if (!Directory.Exists(SourcesPath)) { Log.Fatal("{@SourcesPath} doesn't exist; service has nothing to do without sources", SourcesPath); Stop(); return; } if (!Directory.Exists(SinksPath)) { Log.Warning("{@SinksPath} doesn't exist; service has nothing to do without sinks", SinksPath); } _childDevices.CollectionChanged += (sender, args) => { switch (args.Action) { case NotifyCollectionChangedAction.Add: foreach (IDualShockDevice item in args.NewItems) { Log.Information("Device {Device} got attached via {ConnectionType}", item, item.ConnectionType); foreach (var plugin in SinkPlugins.Select(p => p.Value)) { plugin.DeviceArrived(item); } } break; case NotifyCollectionChangedAction.Remove: foreach (IDualShockDevice item in args.OldItems) { Log.Information("Device {Device} got removed via {ConnectionType}", item, item.ConnectionType); foreach (var plugin in SinkPlugins.Select(p => p.Value)) { plugin.DeviceRemoved(item); } } break; } }; #region MEF //Creating an instance of aggregate catalog. It aggregates other catalogs var aggregateCatalog = new AggregateCatalog(); //Load parts from the current assembly if available var asmCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly()); //Add to the aggregate catalog aggregateCatalog.Catalogs.Add(new DirectoryCatalog(SourcesPath, "*.dll")); aggregateCatalog.Catalogs.Add(new DirectoryCatalog(SinksPath, "*.dll")); aggregateCatalog.Catalogs.Add(asmCatalog); //Crete the composition container var container = new CompositionContainer(aggregateCatalog); // Composable parts are created here i.e. // the Import and Export components assembles here container.ComposeParts(this); #endregion // Log loaded sink plugins foreach (var plugin in SinkPlugins) { Log.Information("Loaded sink plugin {Plugin}", plugin.Metadata["Name"]); plugin.Value.RumbleRequestReceived += (sender, args) => _childDevices[(IDualShockDevice)sender].Rumble(args.LargeMotor, args.SmallMotor); } // Log and enable sources foreach (var emulator in BusEmulators) { Log.Information("Loaded bus emulator {Emulator}", emulator.Metadata["Name"]); emulator.Value.ChildDeviceAttached += (sender, args) => _childDevices.Add(args.Device); emulator.Value.ChildDeviceRemoved += (sender, args) => _childDevices.Remove(args.Device); emulator.Value.InputReportReceived += EmulatorOnInputReportReceived; try { Log.Information("Starting bus emulator {Emulator}", emulator.Metadata["Name"]); emulator.Value.Start(); Log.Information("Bus emulator {Emulator} started successfully", emulator.Metadata["Name"]); } catch (Exception ex) { Log.Error("Failed to start {@emulator}: {@ex}", emulator.Metadata["Name"], ex); } } #region IPC var services = new DelegateServiceFactory(); services.Register <IPairingService>(() => { var service = new PairingService(); service.DeviceListRequested += (sender, args) => _childDevices .Where(d => d.ConnectionType.Equals(DualShockConnectionType.USB)) .Select(d => new DualShockDeviceDescriptor { ClientAddress = new UniqueAddress(d.ClientAddress), ConnectionType = d.ConnectionType, DeviceType = d.DeviceType, HostAddress = new UniqueAddress(d.HostAddress) }).ToList(); service.DevicePairingRequested += (device, args) => _childDevices[device.ClientAddress].PairTo(new PhysicalAddress(args.HostAddress.AddressBytes)); return(service); }); _ipcServer = new HalibutRuntime(services, Configuration.ServerCertificate); _ipcServer.Listen(Configuration.ServerEndpoint); _ipcServer.Trust(Configuration.ClientCertificate.Thumbprint); #endregion }