예제 #1
0
 /// <summary>
 /// For each key in the list increment its count if it exists, else adds it to the dictionary of keys with a count of 1 for the gamepads
 /// </summary>
 /// <param name="listOfButtonPresses"></param>
 public static void GamepadInputUpdate(List <string> listOfButtonPresses)
 {
     try
     {
         _currentProfile?.Gamepad?.AddList(listOfButtonPresses);
     }
     catch (Exception e)
     {
         if (e is ChainingException exception)
         {
             exception.AddErrorToChain("While trying to update the gamepad key counts");
         }
         else
         {
             exception = new ChainingException(e.Message);
             exception.AddErrorToChain("While trying to update the gamepad key counts");
         }
         throw exception;
     }
 }
예제 #2
0
 /// <summary>
 /// Gets the currents profile time
 /// </summary>
 /// <returns>long representing the time spent in the current profile</returns>
 public static long?GetTimeSpent()
 {
     try
     {
         return(_currentProfile?.TimeSpent);
     }
     catch (Exception e)
     {
         if (e is ChainingException exception)
         {
             exception.AddErrorToChain("While trying to get the time spent");
         }
         else
         {
             exception = new ChainingException(e.Message);
             exception.AddErrorToChain("While trying to get the time spent");
         }
         throw exception;
     }
 }
예제 #3
0
 /// <summary>
 /// Increment the count of the key if it exists, else adds it to the dictionary of keys with a count of 1 for the keyboards
 /// </summary>
 /// <param name="key"></param>
 public static void KeyboardInputUpdate(string key)
 {
     try
     {
         _currentProfile?.Keyboard?.AddOne(key);
     }
     catch (Exception e)
     {
         if (e is ChainingException exception)
         {
             exception.AddErrorToChain("While trying to update the keyboard key counts");
         }
         else
         {
             exception = new ChainingException(e.Message);
             exception.AddErrorToChain("While trying to update the keyboard key counts");
         }
         throw exception;
     }
 }
예제 #4
0
 /// <summary>
 /// Add to the dictionary the <paramref name="key"/> with a initialized with <paramref name="value"/>.
 /// Raises the OnAddStatus event
 /// </summary>
 /// <param name="key">the key</param>
 /// <param name="value">number of presses</param>
 public void Add(string key, uint value)
 {
     try
     {
         Keys.GetOrAdd(key, value);
         OnAddStatus?.Invoke(this, new DictionaryEventArgs(key, false));
     }
     catch (Exception e)
     {
         if (e is ChainingException exception)
         {
             exception.AddErrorToChain("While trying to add value in the count dictionary");
         }
         else
         {
             exception = new ChainingException(e.Message);
             exception.AddErrorToChain("While trying to add value in the count dictionary");
         }
         throw exception;
     }
 }
예제 #5
0
 /// <summary>
 /// Empties the dictionary of counts of the current device
 /// </summary>
 public static void ClearCurrentDeviceDictionary()
 {
     try
     {
         var list = new List <string>(CurrentDevice.KeysCount.Keys.Keys);
         CurrentDevice.KeysCount.RemoveList(list);
     }
     catch (Exception e)
     {
         if (e is ChainingException exception)
         {
             exception.AddErrorToChain("While trying clear the currents device keys counts");
         }
         else
         {
             exception = new ChainingException(e.Message);
             exception.AddErrorToChain("While trying clear the currents device keys counts");
         }
         throw exception;
     }
 }
예제 #6
0
 /// <summary>
 /// Remove the key from the dictionary
 /// Raises the event OnUpdateStatus
 /// </summary>
 /// <param name="key"></param>
 /// <returns>true if the operation was successful, false otherwise</returns>
 public bool Remove(string key)
 {
     try
     {
         bool result = Keys.TryRemove(key, out _);
         OnUpdateStatus?.Invoke(this, new DictionaryEventArgs(key, true));
         return(result);
     }
     catch (Exception e)
     {
         if (e is ChainingException exception)
         {
             exception.AddErrorToChain("While trying to remove key from count dictionary");
         }
         else
         {
             exception = new ChainingException(e.Message);
             exception.AddErrorToChain("While trying to remove key from count dictionary");
         }
         throw exception;
     }
 }
예제 #7
0
 /// <summary>
 /// Creates and saves a new profile
 /// </summary>
 /// <param name="outputFolder"></param>
 /// <param name="newProfileName"></param>
 /// <param name="usesGamepad"></param>
 /// <returns></returns>
 public static bool CreateNewProfile(string outputFolder, string newProfileName, bool usesGamepad)
 {
     try
     {
         var newProfile = new Profile(newProfileName, usesGamepad);
         SaveProfile(outputFolder, newProfile);
         return(true);
     }
     catch (Exception e)
     {
         if (e is ChainingException exception)
         {
             exception.AddErrorToChain("While trying to create new profile");
         }
         else
         {
             exception = new ChainingException(e.Message);
             exception.AddErrorToChain("While trying to create new profile");
         }
         throw exception;
     }
 }
예제 #8
0
 /// <summary>
 /// Updates the time spent in the current profile
 /// </summary>
 /// <param name="newTime">TimeSpan to add to the count of time</param>
 public static void UpdateTime(TimeSpan?newTime)
 {
     try
     {
         if (newTime.HasValue && _currentProfile != null)
         {
             _currentProfile.TimeSpent += newTime.Value.Ticks;
         }
     }
     catch (Exception e)
     {
         if (e is ChainingException exception)
         {
             exception.AddErrorToChain("While trying to update time spent");
         }
         else
         {
             exception = new ChainingException(e.Message);
             exception.AddErrorToChain("While trying to update time spent");
         }
         throw exception;
     }
 }
예제 #9
0
 /// <summary>
 /// Updates the time spent in the current profile
 /// </summary>
 /// <param name="timeToAdd">long to add to the count of time</param>
 public static void UpdateTime(long timeToAdd)
 {
     try
     {
         if (timeToAdd > 0 && _currentProfile != null)
         {
             _currentProfile.TimeSpent += timeToAdd;
         }
     }
     catch (Exception e)
     {
         if (e is ChainingException exception)
         {
             exception.AddErrorToChain("While trying to update time spent");
         }
         else
         {
             exception = new ChainingException(e.Message);
             exception.AddErrorToChain("While trying to update time spent");
         }
         throw exception;
     }
 }
예제 #10
0
        /// <summary>
        /// JSON serializes the currently used profile
        /// </summary>
        /// <param name="outputFolder"></param>
        public static void SaveCurrentProfile(string outputFolder)
        {
            try
            {
                if (!Directory.Exists(outputFolder))
                {
                    Directory.CreateDirectory(outputFolder);
                }

                if (_currentProfile != null)
                {
                    using (StreamWriter sw = File.CreateText(outputFolder + "\\" + _currentProfile.Name + ".txt"))
                    {
                        JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions
                        {
                            WriteIndented = true,
                            IncludeFields = true
                        };
                        sw.Write(JsonSerializer.Serialize(_currentProfile, jsonSerializerOptions));
                    }
                }
            }
            catch (Exception e)
            {
                if (e is ChainingException exception)
                {
                    exception.AddErrorToChain("While trying to save the current profile");
                }
                else
                {
                    exception = new ChainingException(e.Message);
                    exception.AddErrorToChain("While trying to save the current profile");
                }
                throw exception;
            }
        }
예제 #11
0
 /// <summary>
 /// Sets up the handlers for the possible events of a device
 /// </summary>
 /// <param name="newKeyPress"></param>
 /// <param name="oldKeyPress"></param>
 /// <param name="addedList"></param>
 /// <param name="removeList"></param>
 public static void SetupDeviceHandlers(DictionaryWithEvents.DictionaryEvent newKeyPress, DictionaryWithEvents.DictionaryEvent oldKeyPress, DictionaryWithEvents.DictionaryEvent addedList, DictionaryWithEvents.DictionaryEvent removeList)
 {
     try
     {
         CurrentDevice.KeysCount.OnAddStatus    += newKeyPress;
         CurrentDevice.KeysCount.OnUpdateStatus += oldKeyPress;
         CurrentDevice.KeysCount.OnAddList      += addedList;
         CurrentDevice.KeysCount.OnRemoveList   += removeList;
         CurrentDevice.KeysCount.HasSubscribers  = true;
     }
     catch (Exception e)
     {
         if (e is ChainingException exception)
         {
             exception.AddErrorToChain("While trying to set up device handlers");
         }
         else
         {
             exception = new ChainingException(e.Message);
             exception.AddErrorToChain("While trying to set up device handlers");
         }
         throw exception;
     }
 }
예제 #12
0
        protected override bool CreateImageForKey(string key)
        {
            // Since the majority of buttons are unique and predefined and easily recognizable the images for them are in templates,
            // this makes is so that those "template" images are returned without writing anything on them if needed
            try
            {
                if (ImagesLoaded == false)
                {
                    return(false);
                }

                if (Templates.Keys.Contains(key))
                {
                    Images.GetOrAdd(key, (Image)Templates[key].Clone());
                }
                else
                {
                    Images.GetOrAdd(key, WriteOnTemplate((Image)Templates["key"].Clone(), key));
                }

                return(true);
            }
            catch (Exception ex)
            {
                if (ex is ChainingException exception)
                {
                    exception.AddErrorToChain("While trying to create a gamepad image");
                }
                else
                {
                    exception = new ChainingException(ex.Message);
                    exception.AddErrorToChain("While trying to create a gamepad image");
                }
                throw exception;
            }
        }
예제 #13
0
        /// <summary>
        /// Loads all images and templates in memory used in a worker thread
        /// </summary>
        /// <param name="worker">worker argument used to see if loading should be cancelled</param>
        /// <returns>true if the images were loaded, false if the worker was  interrupted</returns>
        public bool LoadImages(BackgroundWorker worker)
        {
            try
            {
                if (ImagesPath == "")
                {
                    throw new NullReferenceException("path to images cannot be empty");
                }

                foreach (var file in Directory.EnumerateFiles(Path.Join(ImagesPath, "templates/")))
                {
                    if (file.EndsWith(".png"))
                    {
                        //frees the image after loading them so they can be freely used in other operations, otherwise the handle to the file would be
                        // kept by the app
                        var auxImage = Image.FromFile(file);
                        Templates.GetOrAdd(Path.GetFileNameWithoutExtension(file), new Bitmap(auxImage));

                        //Images are evil, they must be both exposed and all all references removed for the GC to take'em
                        auxImage.Dispose();

                        if (worker.CancellationPending)
                        {
                            ImagesLoaded = false;
                            foreach (var key in Templates.Keys)
                            {
                                Templates[key].Dispose();
                            }
                            Templates.Clear();
                            return(false);
                        }
                    }
                }

                foreach (var file in Directory.EnumerateFiles(ImagesPath))
                {
                    if (file.EndsWith(".png"))
                    {
                        Console.WriteLine(Path.GetFileNameWithoutExtension(file));
                        var auxImage = Image.FromFile(file);
                        Images.GetOrAdd(Path.GetFileNameWithoutExtension(file), new Bitmap(auxImage));
                        auxImage.Dispose();
                        if (worker.CancellationPending)
                        {
                            ImagesLoaded = false;

                            foreach (var key in Templates.Keys)
                            {
                                Templates[key].Dispose();
                            }
                            foreach (var key in Images.Keys)
                            {
                                Images[key].Dispose();
                            }

                            Templates.Clear();
                            Images.Clear();
                            return(false);
                        }
                    }
                }

                ImagesLoaded = true;
                return(true);
            }
            catch (Exception e)
            {
                var exception = new ChainingException(e.Message);
                exception.AddErrorToChain("While trying to load images");
                throw exception;
            }
        }
예제 #14
0
        /// <summary>
        /// verify if a gamepad is connected, if it is then check which buttons are pressed and the directions of the thumb sticks,
        /// if no gamepad is connected change the timer to 1 every 5 seconds
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="eventArgs"></param>
        static void CheckGamepad(object?sender, EventArgs eventArgs)
        {
            try
            {
                //Console.WriteLine("checked for gamepad input");
                switch (XInputGetState(0, out CurrentState))
                {
                case ERROR_SUCCESS:
                {
                    // if a controller was just connected go back to checking for input ~60 times per second
                    if (frameTimer.Interval == 5000)
                    {
                        frameTimer.Interval = 15;
                    }
                    if (CurrentState.dwPacketNumber != LastState.dwPacketNumber)
                    {
                        var listOfButtonPresses = new List <string>();

                        //apply the bitmask for each button and take it as a press only if the result is not equal to 0 and if the previous state was equal to 0
                        if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) != 0 &&
                            (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP) == 0)
                        {
                            listOfButtonPresses.Add("D_pad_up");
                        }

                        if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) != 0 &&
                            (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_DOWN) == 0)
                        {
                            listOfButtonPresses.Add("D_pad_down");
                        }

                        if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) != 0 &&
                            (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_RIGHT) == 0)
                        {
                            listOfButtonPresses.Add("D_pad_right");
                        }

                        if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) != 0 &&
                            (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_LEFT) == 0)
                        {
                            listOfButtonPresses.Add("D_pad_left");
                        }

                        if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_START) != 0 &&
                            (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_START) == 0)
                        {
                            listOfButtonPresses.Add("start");
                        }

                        if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) != 0 &&
                            (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_BACK) == 0)
                        {
                            listOfButtonPresses.Add("back");
                        }


                        if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) != 0 &&
                            (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_SHOULDER) == 0)
                        {
                            listOfButtonPresses.Add("left_shoulder");
                        }

                        if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) != 0 &&
                            (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_SHOULDER) == 0)
                        {
                            listOfButtonPresses.Add("right_shoulder");
                        }


                        if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) != 0 &&
                            (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB) == 0)
                        {
                            listOfButtonPresses.Add("left_thumb");
                        }

                        if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) != 0 &&
                            (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) == 0)
                        {
                            listOfButtonPresses.Add("right_thumb");
                        }

                        if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_A) != 0 &&
                            (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_A) == 0)
                        {
                            listOfButtonPresses.Add("a");
                        }

                        if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_B) != 0 &&
                            (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_B) == 0)
                        {
                            listOfButtonPresses.Add("b");
                        }

                        if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_X) != 0 &&
                            (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_X) == 0)
                        {
                            listOfButtonPresses.Add("x");
                        }

                        if ((CurrentState.Gamepad.wButtons & XINPUT_GAMEPAD_Y) != 0 &&
                            (LastState.Gamepad.wButtons & XINPUT_GAMEPAD_Y) == 0)
                        {
                            listOfButtonPresses.Add("y");
                        }

                        if (CurrentState.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD &&
                            LastState.Gamepad.bLeftTrigger < XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
                        {
                            listOfButtonPresses.Add("left_trigger");
                        }

                        if (CurrentState.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD &&
                            LastState.Gamepad.bRightTrigger < XINPUT_GAMEPAD_TRIGGER_THRESHOLD)
                        {
                            listOfButtonPresses.Add("right_trigger");
                        }

                        //take care of the cases where the absolute would underflow
                        if (CurrentState.Gamepad.sThumbLY == short.MinValue)
                        {
                            CurrentState.Gamepad.sThumbLY = short.MinValue + 2;
                        }

                        if (CurrentState.Gamepad.sThumbLX == short.MinValue)
                        {
                            CurrentState.Gamepad.sThumbLX = short.MinValue + 2;
                        }

                        var directionL = MouseHookClass.MovementDirection(
                            new Point(CurrentState.Gamepad.sThumbLX, CurrentState.Gamepad.sThumbLY),
                            new Point(0, 0));
                        // update the direction of the left thumb stick only if it is outside of the dead zone and the previous state was inside the dead zone
                        // or if the direction is different
                        if ((Math.Abs(CurrentState.Gamepad.sThumbLY) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ||
                             Math.Abs(CurrentState.Gamepad.sThumbLX) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) &&
                            !(Math.Abs(LastState.Gamepad.sThumbLY) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ||
                              Math.Abs(LastState.Gamepad.sThumbLX) > XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) || (directionL != null && directionL != LastDirectionL))
                        {
                            if (directionL != null)
                            {
                                listOfButtonPresses.Add("left_thumb_move_" + directionL);
                                LastDirectionL = directionL;
                            }
                        }

                        //take care of the cases where the absolute would underflow
                        if (CurrentState.Gamepad.sThumbRY == short.MinValue)
                        {
                            CurrentState.Gamepad.sThumbRY = short.MinValue + 2;
                        }

                        if (CurrentState.Gamepad.sThumbRX == short.MinValue)
                        {
                            CurrentState.Gamepad.sThumbRX = short.MinValue + 2;
                        }

                        var directionR = MouseHookClass.MovementDirection(
                            new Point(CurrentState.Gamepad.sThumbRX, CurrentState.Gamepad.sThumbRY),
                            new Point(0, 0));
                        // update the direction of the right thumb stick only if it is outside of the dead zone and the previous state was inside the dead zone
                        // or if the direction is different
                        if ((Math.Abs(CurrentState.Gamepad.sThumbRX) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE ||
                             Math.Abs(CurrentState.Gamepad.sThumbRY) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) &&
                            !(Math.Abs(LastState.Gamepad.sThumbRX) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE ||
                              Math.Abs(LastState.Gamepad.sThumbRY) > XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) || (directionR != null && directionR != LastDirectionR))
                        {
                            if (directionR != null)
                            {
                                listOfButtonPresses.Add("right_thumb_move_" + directionR);
                                LastDirectionR = directionR;
                            }
                        }



                        if (listOfButtonPresses.Count > 0)
                        {
                            ProfileManager.GamepadInputUpdate(listOfButtonPresses);
                        }

                        LastState = CurrentState;
                    }

                    break;
                }

                case ERROR_DEVICE_NOT_CONNECTED:
                {
                    // if no gamepad is connected then search for input only once every 5 seconds
                    if (frameTimer.Interval != 5000)
                    {
                        frameTimer.Interval = 5000;
                    }
                    break;
                }
                }
            }
            catch (Exception e)
            {
                if (e is ChainingException exception)
                {
                    exception.AddErrorToChain("While trying to read gamepad input");
                }
                else
                {
                    exception = new ChainingException(e.Message);
                    exception.AddErrorToChain("While trying to read gamepad input");
                }
                throw exception;
            }
        }
예제 #15
0
        /// <summary>
        /// handle the mouse event
        /// </summary>
        /// <param name="nCode"></param>
        /// <param name="wParam">parameter describing the type of event</param>
        /// <param name="lParam">pointer to a structure in memory containing the event parameters</param>
        /// <returns></returns>
        private static IntPtr HandleMouseEvent(int nCode, IntPtr wParam, IntPtr lParam)
        {
            try
            {
                //get the parameters to which the pointer point to
                var mouseStruct = (LowLevelMouseStructure)(Marshal.PtrToStructure(lParam, typeof(LowLevelMouseStructure)) ?? throw new NullReferenceException("Mouse structure was null"));

                // add to the CurrentProfile mouse dictionary the corresponding key
                switch ((int)wParam)
                {
                case 513:
                {
                    ProfileManager.MouseInputUpdate("left_button");
                    break;
                }

                case 516:
                {
                    ProfileManager.MouseInputUpdate("right_button");
                    break;
                }

                case 519:
                {
                    ProfileManager.MouseInputUpdate("middle_button");
                    break;
                }

                case 523:
                {
                    var button = 3 + short.Parse(mouseStruct.MouseData.ToString("X")) / 10000;
                    ProfileManager.MouseInputUpdate("Button " + button);
                    break;
                }

                case 522:
                {
                    if (_lastMouseWheelMovement >= 0 && mouseStruct.MouseData < 0 ||
                        _lastMouseWheelMovement <= 0 && mouseStruct.MouseData > 0 ||
                        mouseStruct.TimeStamp - _lastMouseUpdate > 1500)
                    {
                        _lastMouseWheelMovement = mouseStruct.MouseData;
                        _lastMouseUpdate        = (int)mouseStruct.TimeStamp;
                        ProfileManager.MouseInputUpdate(mouseStruct.MouseData > 0 ? "scroll_up" : "scroll_down");
                    }

                    break;
                }

                case 512:
                {
                    // detect a mouse movement only if the new coordinates are outside of a dead zone and if the time since the last update is big enough or if the direction
                    // is different.
                    // Also remember that the Y on  monitor goes different than on a normal 2D space, so the true Y is height of the monitor - the given Y coordinate
                    var direction = MovementDirection(new Point(mouseStruct.Point.X, Screen.PrimaryScreen.Bounds.Height - mouseStruct.Point.Y), _mousePos);
                    var distance  = Math.Sqrt(Math.Pow((mouseStruct.Point.X - _mousePos.X), 2) +
                                              Math.Pow((Screen.PrimaryScreen.Bounds.Height - mouseStruct.Point.Y - _mousePos.Y), 2));

                    if (direction != null && (mouseStruct.TimeStamp - _lastMouseUpdate > 750 ||
                                              !direction.Equals(_lastMouseMovement)) && distance > 30)
                    {
                        _lastMouseWheelMovement = 0;
                        _lastMouseUpdate        = (int)mouseStruct.TimeStamp;
                        _mousePos = new Point(mouseStruct.Point.X, Screen.PrimaryScreen.Bounds.Height - mouseStruct.Point.Y);
                        ProfileManager.MouseInputUpdate(direction);
                        _lastMouseMovement = direction;
                    }

                    break;
                }
                }

                return(CallNextHookEx(_mouseHookId, nCode, wParam, lParam));
            }
            catch (Exception e)
            {
                if (e is ChainingException exception)
                {
                    exception.AddErrorToChain("While trying to read mouse input");
                }
                else
                {
                    exception = new ChainingException(e.Message);
                    exception.AddErrorToChain("While trying to read mouse input");
                }
                throw exception;
            }
        }