├── .gitignore ├── Example Pages ├── WintoolsExample1.tpz └── WintoolsExample2.tpz ├── LICENSE ├── README.md ├── Wintools-by-Killler_BOSS.png ├── new_src ├── WinTool.py ├── audioMeter.py ├── entry.tp └── utils │ ├── TextToSpeech.py │ ├── __init__.py │ ├── audioController.py │ ├── audioSwitch.py │ ├── clipboard.py │ ├── magnifier.py │ ├── monitorPrimary.py │ ├── policyconfig.py │ ├── powerplan.py │ ├── rotateDisplay.py │ ├── util.py │ ├── virtualDesktop.py │ ├── winNotification.py │ └── winShutdown.py ├── patchnotes.txt └── src ├── AudioDeviceCmdlets.dll ├── compile.py ├── entry.tp ├── icon.ico ├── icon.png ├── main.py ├── requirements.txt └── utils └── util.py /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.pyc 3 | -------------------------------------------------------------------------------- /Example Pages/WintoolsExample1.tpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KillerBOSS2019/WinTools/d5cbbe721b5ff150e7b3a4afe9dca41a82c31ca5/Example Pages/WintoolsExample1.tpz -------------------------------------------------------------------------------- /Example Pages/WintoolsExample2.tpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KillerBOSS2019/WinTools/d5cbbe721b5ff150e7b3a4afe9dca41a82c31ca5/Example Pages/WintoolsExample2.tpz -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 IMISSED 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![pngwing com_11](https://user-images.githubusercontent.com/55416314/153131886-42c0448d-81f8-49f3-bc38-693ae2341aaf.png) 2 | ## WinTool Plugin 3 | 4 | 5 | 6 | - [WinTool Plugin](#wintool-plugin) 7 | - [Description](#description) 8 | - [Actions](#actions) 9 | - [States](#states) 10 | - [Installation Guide](#installation-guide) 11 | - [Settings Overview](#settings-Overview) 12 | - [info](#info) 13 | 14 | 15 | ## Description 16 | WinTool is multi Tools that is made to work with Windows machine. 17 | 18 | ## Actions 19 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [VolumeMixer] Mute/Unmute process volume
20 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [VOLUME MIXER] Increase/Decrease process volume (slider control available) 21 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [VOLUME MIXER] Increase/Decrease process volume (slider control available) 22 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Sound] Change Input/Output Device 23 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Mouse] Toggle Mouse Down/Up 24 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Mouse] Stop X, Y Update (Togglable) 25 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Mouse] Teleport Mouse X, Y with delay, animation 26 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Mouse] Advanced Mouse Click 27 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Capture] Display to File / Clipboard 28 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Capture] Window to File / Clipboard 29 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Capture] Window to File / Clipboard (*Wildcard) 30 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Capture] Current Active Window File / Clipboard 31 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Utility] Text To Speech: Speak 32 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Utility] Text To Speech: Stop 33 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Utility] Move Application To Monitor Left/Right 34 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Utility] Shutdown Computer in (X) minutes 35 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Utility] Change Powerplan 36 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Utility] System Settings 37 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Utility] Change Primary Monitor 38 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Utility] Rotate Display / Monitor 39 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Utility] Windows Notifcation 40 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Utility] Magnifier Glass 41 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Utility] On-Screen Keyboard 42 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Utility] Emoji Panel 43 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Utility] Text / Value to Clipboard 44 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Utility] Virtual Desktop: Next / Previous 45 | - ![#f03c15](https://i.imgur.com/n8joDW9.png) [Utility] Virtual Desktop: Move Current Window to # 46 | 47 | ## States 48 | - [State] [Advance Mouse] Current Mouse X pos 49 | - [State] [Advance Mouse] Current Mouse Y pos 50 | - [State] [Sound] Get Current Output Device 51 | - [State] [Sound] Get Current Input Device 52 | - [State] [Sound] Application Volume (Create states base on Volume Mixer) 53 | - [State] [Sound] Application is Muted (Create states base on Volume Mixer) 54 | - [State] [System] Get Current Focused Application Name 55 | - [State] [System] Total Bytes Received 56 | - [State] [System] Total Bytes Send 57 | - [State] [System] Disk Read Total 58 | - [State] [System] Disk Write Total 59 | - [State] [System] Active Window Count 60 | - [State] [System] Active Power Plan 61 | - [State] [System] Computer Uptime 62 | - [State] [IP] IP Address 63 | - [State] [IP] City 64 | - [State] [IP] Country 65 | - [State] [IP] Region 66 | - [State] [IP] Timezone 67 | - [State] [IP] Internet Provider 68 | 69 | 70 | ## Installation Guide 71 | 1. Go to [Releases](https://github.com/KillerBOSS2019/WinTools/releases) and Latest build should be on the top 72 | 2. Then scroll down little until you see "Assets" [Image/Assets.png] Click arrow button 73 | 3. And then you should see a file atteched that says `WinTool.V1.0.tpp` something like that. Download it 74 | 4. Then open TouchPortal if TouchPortal isnt open. Click on the settings button near the email icon and Select `Import Plug-in...` 75 | 5. Then Select the .TPP file that you've downloaded. It should be located in Downloads folder. 76 | 6. Next TouchPortal will warn you that you've installed a Plugin called `Windows-Tools`. You can click `Trust Always` if you dont want this to popup everytime you boot. Otherwise click OK for Trust this . 77 | 7. Next TouchPortal will popup a Window says `Plug-in Imported successful` You can click `OK` 78 | 8. If this was your first Plugin you will need to reboot TouchPortal. Otherwise if plugin doesnt work you could also try reboot TouchPortal 79 | 9. That should be all the steps you need to Install the Plugin. If you have issues feel free contect on Discord or Github on issue tab 80 | 81 | ## Settings Overview 82 | 83 | ### Windows-Tools Settings 84 | - Update Interval: Network Up-Down(INCOMPLETE) 85 | - In seconds of how offen that it will update Network data 86 | - Update Interval: Hard Drive 87 | - In seconds of how offen that it will update infos about storage drive 88 | - Update Interval: Active Monitors 89 | - In seconds of how offen that it will ipdate active monitors. This is also used for Monitor drop-down list for action 90 | - Update Inerval: Active Windows 91 | - In seconds of how offen that it will ipdate active window state 92 | - Update Interval: Active Virtual Desktops 93 | - In seconds of how offen that it will check for Virtual Desktop states 94 | 95 | ### To access Plugin Settings 96 | 1. Click Settings button near the email icon 97 | 2. Select `Settings...` 98 | 3. It should open Settings window and on the left side you should see `Plug-Ins` tab. Click on that 99 | 4. Then you should see a drop-down Select `Windows-Tools`. and you should see all the settings 100 | 101 | ## Info 102 | Feel free to suggest a pull request for new features, improvements, or documentation. If you are not sure how to proceed with something, please start an Issue at the GitHub repository. 103 | -------------------------------------------------------------------------------- /Wintools-by-Killler_BOSS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KillerBOSS2019/WinTools/d5cbbe721b5ff150e7b3a4afe9dca41a82c31ca5/Wintools-by-Killler_BOSS.png -------------------------------------------------------------------------------- /new_src/WinTool.py: -------------------------------------------------------------------------------- 1 | import os 2 | from time import sleep 3 | 4 | import pygetwindowmp as pygetwindow 5 | import pythoncom 6 | import TouchPortalAPI 7 | from pycaw.constants import AudioSessionState 8 | from pycaw.magic import MagicManager # ## These are used in main.py 9 | from pycaw.magic import MagicSession 10 | from TouchPortalAPI import TYPES 11 | 12 | from utils import audioController, clipboard, util 13 | import threading 14 | from utils.magnifier import * 15 | from utils.virtualDesktop import * 16 | from utils.TextToSpeech import * 17 | from utils.util import winextra, windowsSettings 18 | 19 | TPClient = TouchPortalAPI.Client('Windows-Tools') 20 | 21 | volumeprocess = ["Master Volume", "Current app"] 22 | audio_exempt_list = [] 23 | running = False 24 | 25 | 26 | def updateVolumeMixerChoicelist(): 27 | TPClient.choiceUpdate('KillerBOSS.TP.Plugins.VolumeMixer.Increase/DecreaseVolume.process', volumeprocess) 28 | TPClient.choiceUpdate('KillerBOSS.TP.Plugins.VolumeMixer.Mute/Unmute.process', volumeprocess) 29 | TPClient.choiceUpdate("KillerBOSS.TP.Plugins.VolumeMixer.slidercontrol", volumeprocess) 30 | 31 | def removeAudioState(app_name): 32 | global volumeprocess 33 | TPClient.removeStateMany([ 34 | f"KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{app_name}.muteState", 35 | f"KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{app_name}", 36 | f"KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{app_name}.active"]) 37 | volumeprocess.remove(app_name) 38 | updateVolumeMixerChoicelist() # Update with new changes 39 | 40 | def audioStateManager(app_name): 41 | global volumeprocess 42 | print("AUDIO EXEMPT LIST", audio_exempt_list) 43 | 44 | if app_name not in volumeprocess: 45 | TPClient.createStateMany([ 46 | { 47 | "id": f'KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{app_name}.muteState', 48 | "desc": f"{app_name} Mute State", 49 | "parentGroup": "Audio process state", 50 | "value": "" 51 | }, 52 | { 53 | "id": f'KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{app_name}', 54 | "desc": f"{app_name} Volume", 55 | "parentGroup": "Audio process state", 56 | "value": "" 57 | }, 58 | { 59 | "id": f'KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{app_name}.active', 60 | "desc": f"{app_name} Active", 61 | "parentGroup": "Audio process state", 62 | "value": "" 63 | }, 64 | ]) 65 | volumeprocess.append(app_name) 66 | 67 | """UPDATING CHOICES WITH GLOBALS""" 68 | updateVolumeMixerChoicelist() 69 | print(f"{app_name} State Added") 70 | 71 | """ Checking for Exempt Audio""" 72 | if app_name in audio_exempt_list: 73 | removeAudioState(app_name) 74 | 75 | import ctypes 76 | 77 | import psutil 78 | import win32process 79 | import pyautogui 80 | 81 | 82 | def getActiveExecutablePath(): 83 | hWnd = ctypes.windll.user32.GetForegroundWindow() 84 | if hWnd == 0: 85 | return None # Note that this function doesn't use GetLastError(). 86 | else: 87 | _, pid = win32process.GetWindowThreadProcessId(hWnd) 88 | return psutil.Process(pid).exe() 89 | 90 | class WinAudioCallBack(MagicSession): 91 | def __init__(self): 92 | super().__init__(volume_callback=self.update_volume, 93 | mute_callback=self.update_mute, 94 | state_callback=self.update_state) 95 | 96 | # ______________ DISPLAY NAME ______________ 97 | self.app_name = self.magic_root_session.app_exec 98 | #print(f":: new session: {self.app_name}") 99 | 100 | if self.app_name not in audio_exempt_list: 101 | # set initial: 102 | self.update_mute(self.mute) 103 | self.update_state(self.state) 104 | self.update_volume(self.volume) 105 | 106 | 107 | def update_state(self, new_state): 108 | """ 109 | when status changed 110 | (see callback -> AudioSessionEvents -> OnStateChanged) 111 | """ 112 | if self.app_name not in audio_exempt_list: 113 | if new_state == AudioSessionState.Inactive: 114 | # AudioSessionStateInactive 115 | """Sesssion is Inactive""" 116 | #print(f"{self.app_name} not active") 117 | TPClient.stateUpdate(f'KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{self.app_name}.active',"False") 118 | 119 | elif new_state == AudioSessionState.Active: 120 | """Session Active""" 121 | #print(f"{self.app_name} is an Active Session") 122 | TPClient.stateUpdate(f'KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{self.app_name}.active',"True") 123 | 124 | elif new_state == AudioSessionState.Expired: 125 | """Removing Expired States""" 126 | removeAudioState(self.app_name) 127 | 128 | 129 | def update_volume(self, new_volume): 130 | """ 131 | when volume is changed externally - Updating Sliders and Volume States 132 | (see callback -> AudioSessionEvents -> OnSimpleVolumeChanged ) 133 | """ 134 | if self.app_name not in audio_exempt_list: 135 | TPClient.stateUpdate(f'KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{self.app_name}',str(round(new_volume*100))) 136 | #print(f"{self.app_name} NEW VOLUME", str(round(new_volume*100))) 137 | TPClient.send({ 138 | "type":"connectorUpdate", 139 | "connectorId":f"pc_Windows-Tools_KillerBOSS.TP.Plugins.VolumeMixer.connectors.APPcontrol|KillerBOSS.TP.Plugins.VolumeMixer.slidercontrol={self.app_name}", 140 | "value": round(new_volume*100) 141 | }) 142 | 143 | """Checking for Current App If Its Active, Adjust it also""" 144 | if (activeWindow := getActiveExecutablePath()) != "": 145 | if os.path.basename(activeWindow) == self.app_name: 146 | TPClient.send({ 147 | "type":"connectorUpdate", 148 | "connectorId":f"pc_Windows-Tools_KillerBOSS.TP.Plugins.VolumeMixer.connectors.APPcontrol|KillerBOSS.TP.Plugins.VolumeMixer.slidercontrol=Current app", 149 | "value": round(new_volume*100) 150 | }) 151 | else: 152 | TPClient.send({ 153 | "type":"connectorUpdate", 154 | "connectorId":f"pc_Windows-Tools_KillerBOSS.TP.Plugins.VolumeMixer.connectors.APPcontrol|KillerBOSS.TP.Plugins.VolumeMixer.slidercontrol=Current app", 155 | "value": 0 156 | }) 157 | 158 | def update_mute(self, muted): 159 | """ when mute state is changed by user or through other app """ 160 | 161 | if self.app_name not in audio_exempt_list: 162 | audioStateManager(self.app_name) 163 | 164 | if muted: 165 | #print(f"{self.app_name} is unmuted") 166 | TPClient.stateUpdate(f"KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{self.app_name}.muteState", "Muted") 167 | # TPClient.stateUpdate("KillerBOSS.TP.Plugins.state.test", "True") 168 | else: 169 | #print(f"{self.app_name} is muted") 170 | TPClient.stateUpdate(f"KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{self.app_name}.muteState", "Un-Muted") 171 | # TPClient.stateUpdate("KillerBOSS.TP.Plugins.state.test", "False") 172 | 173 | def stateUpdate(): 174 | counter = 0 175 | while running: 176 | sleep(0.1) 177 | counter += 1 178 | if counter%2 == 0: 179 | """ 180 | Update every 2 seconds 181 | """ 182 | TPClient.stateUpdate("KillerBOSS.TP.Plugins.Application.currentFocusedAPP", pygetwindow.getActiveWindowTitle()) 183 | 184 | if counter%5 == 0: 185 | TPClient.send({ 186 | "type":"connectorUpdate", 187 | "connectorId":"pc_Windows-Tools_KillerBOSS.TP.Plugins.VolumeMixer.connectors.APPcontrol|KillerBOSS.TP.Plugins.VolumeMixer.slidercontrol=Master Volume", 188 | "value": str(audioController.getMasterVolume()) 189 | }) 190 | 191 | mp = pyautogui.position() ## Making the call for mouse position once instead of twice.. cause performance :) 192 | TPClient.stateUpdateMany([ 193 | { 194 | "id": f'KillerBOSS.TP.Plugins.AdvanceMouse.MousePos.X', 195 | "value": str(mp[0]) 196 | }, 197 | { 198 | "id": f'KillerBOSS.TP.Plugins.AdvanceMouse.MousePos.Y', 199 | "value": str(mp[1]) 200 | }]) 201 | 202 | if counter >= 40: counter = 0 203 | 204 | @TPClient.on(TYPES.onConnect) 205 | def startManager(data): 206 | global running 207 | """Checking if Plugin needs updated""" 208 | github_check = TouchPortalAPI.Tools.updateCheck("KillerBOSS2019", "WinTools") 209 | plugin_version = str(data['pluginVersion']) 210 | plugin_version = plugin_version[:1] + "." + plugin_version[1:] 211 | if github_check[1:4] != plugin_version[0:3]: 212 | TPClient.showNotification( 213 | notificationId="KillerBOSS.TP.Plugins.Update_Check", 214 | title=f"WinTools v{github_check[1:4]} is available", 215 | msg="A new Wintools Version is available and ready to Download. This may include Bug Fixes and or New Features", 216 | options= [ 217 | { 218 | "id":"Download Update", 219 | "title":"Click here to Update" 220 | } 221 | ]) 222 | 223 | running = True 224 | 225 | """Updating Choices for Windows Settings options from util.py""" 226 | TPClient.choiceUpdate("KillerBOSS.TP.Plugins.winsettings.choice", util.windowsSettings()) 227 | pythoncom.CoInitialize() # This somehow solves OSError: [WinError -2147221008] CoInitialize has not been called 228 | try: 229 | MagicManager.magic_session(WinAudioCallBack) 230 | except NotImplementedError as err: 231 | print(f"--------- Magic already in session!! ---------\n------{err}------") 232 | 233 | thread1 = threading.Thread(target=stateUpdate()) 234 | thread1.start() 235 | 236 | @TPClient.on(TYPES.onSettingUpdate) 237 | def settingHandler(data): 238 | global audio_exempt_list 239 | 240 | audio_exempt_list = data['values'][6]['Audio State Exemption List'] 241 | if audio_exempt_list == "Enter '.exe' name seperated by a comma for more than 1": audio_exempt_list = [] 242 | 243 | @TPClient.on(TouchPortalAPI.TYPES.onNotificationOptionClicked) 244 | def notificationEvent(data): 245 | print(data) 246 | if data['optionId'] == 'Download Update': 247 | print("Directing user to download url") 248 | github_check = TouchPortalAPI.Tools.updateCheck("KillerBOSS2019", "WinTools") 249 | util.runCommandLine(f"Start https://github.com/KillerBOSS2019/WinTools/releases/tag/{github_check}") 250 | 251 | @TPClient.on(TYPES.onAction) 252 | def actionManager(data): 253 | 254 | # Audio action manager 255 | if data['actionId'] == 'KillerBOSS.TP.Plugins.VolumeMixer.Mute/Unmute': 256 | if data['data'][0]['value'] is not '': 257 | audioController.muteAndUnMute(data['data'][0]['value'], data['data'][1]['value']) 258 | if data['actionId'] == 'KillerBOSS.TP.Plugins.VolumeMixer.Increase/DecreaseVolume': 259 | audioController.volumeChanger(data['data'][0]['value'], data['data'][1]['value'], data['data'][2]['value']) 260 | 261 | if data['actionId'] == 'KillerBOSS.TP.Plugins.VolumeMixer.SetmasterVolume': 262 | audioController.setMasterVolume(data['data'][0]['value']) 263 | 264 | # clipboard action manager 265 | if data['actionId'] == "KillerBOSS.TP.Plugins.window.current": 266 | if data['data'][0]['value'] == "Clipboard": 267 | current_window = pygetwindow.getActiveWindowTitle() 268 | clipboard.screenshot_window(capture_type=3, window_title=current_window, clipboard=True) 269 | 270 | elif data['data'][0]['value'] == "File": 271 | current_window = pygetwindow.getActiveWindowTitle() 272 | afile_name = (data['data'][1]['value']) +"/" +(data['data'][2]['value']) 273 | clipboard.screenshot_window(capture_type=3, window_title=current_window, clipboard=False, save_location=afile_name) 274 | 275 | if data['actionId'] == "KillerBOSS.TP.Plugins.screencapture.window.file.wildcard": 276 | global windows_active 277 | windows_active = util.get_windows() 278 | for thing in windows_active: 279 | if data['data'][0]['value'].lower() in thing.lower(): 280 | print("We found", thing) 281 | if data['data'][4]['value'] == "Clipboard": 282 | clipboard.screenshot_window(capture_type=int(data['data'][1]['value']), window_title=thing, clipboard=True) 283 | 284 | elif data['data'][4]['value'] == "File": 285 | print("File stuf") 286 | afile_name = (data['data'][2]['value']) +"/" +(data['data'][3]['value']) 287 | clipboard.screenshot_window(capture_type=int(data['data'][1]['value']), window_title=thing, clipboard=False, save_location=afile_name) 288 | break 289 | 290 | if data['actionId'] == "KillerBOSS.TP.Plugins.screencapture.full.file": 291 | if data['data'][1]['value'] == "Clipboard": 292 | try: 293 | clipboard.screenshot_monitor(monitor_number=(data['data'][0]['value']), clipboard=True) 294 | except: 295 | pass 296 | elif data['data'][1]['value'] == "File": 297 | try: 298 | afile_name = (data['data'][2]['value']) +"/" +(data['data'][3]['value']) 299 | clipboard.screenshot_monitor(monitor_number=(data['data'][0]['value']), filename=afile_name, clipboard=False) 300 | except: 301 | pass 302 | 303 | if data['actionId'] == "KillerBOSS.TP.Plugins.screencapture.window.file": 304 | if (data['data'][0]['value']): 305 | if data['data'][4]['value'] == "Clipboard": 306 | clipboard.screenshot_window(capture_type=int(data['data'][1]['value']), window_title=data['data'][0]['value'], clipboard=True) 307 | if data['data'][4]['value'] == "File": 308 | afile_name = (data['data'][2]['value']) +"/" +(data['data'][3]['value']) 309 | clipboard.screenshot_window(capture_type=int(data['data'][1]['value']), window_title=data['data'][0]['value'], clipboard=False, save_location=afile_name) 310 | 311 | if data['actionId'] == "KillerBOSS.TP.Plugins.capture.clipboard": 312 | clipboard.send_to_clipboard("text", data['data'][0]['value'] ) 313 | 314 | if data['actionId'] == "KillerBOSS.TP.Plugins.capture.clipboard.toValue": 315 | """Save Clipboard Data to a Custom TP Value""" 316 | TPClient.stateUpdate(stateId=data['data'][0]['value'], stateValue=str(clipboard.get_clipboard_data())) 317 | 318 | # Mouse action manager 319 | if data['actionId'] == 'KillerBOSS.TP.Plugins.AdvanceMouse.HoldDownToggle': 320 | if data['data'][0]['value'] == 'Down': 321 | pyautogui.mouseDown(button=(data['data'][1]['value']).lower()) 322 | elif data['data'][0]['value'] == "Up": 323 | pyautogui.mouseUp(button=(data['data'][1]['value']).lower()) 324 | if data['actionId'] == "KillerBOSS.TP.Plugins.AdvanceMouse.teleport": 325 | util.AdvancedMouseFunction(int(data['data'][0]['value']),int(data['data'][1]['value']), int(data['data'][3]['value']), data['data'][2]['value']) 326 | if data['actionId'] == "KillerBOSS.TP.Plugins.AdvanceMouse.MouseClick": 327 | pyautogui.click(clicks=int(data['data'][0]['value']), button=data['data'][2]['value'], interval=float(data['data'][1]['value'])) 328 | if data['actionId'] == 'KillerBOSS.TP.Plugins.AdvanceMouse.Function': 329 | try: 330 | pyautogui.move(int(data['data'][0]['value']), int(data['data'][1]['value'])) 331 | except Exception: 332 | pass 333 | 334 | if data['actionId'] == "KillerBOSS.TP.Plugins.TextToSpeech.speak": 335 | TTSThread = threading.Thread(target=TextToSpeech, daemon=True, args=(data['data'][1]['value'], data['data'][0]['value'], int( 336 | data['data'][2]['value']), int(data['data'][3]['value']), data['data'][4]['value'])) 337 | TTSThread.start() 338 | 339 | if data['actionId'] == "KillerBOSS.TP.Plugins.winextra.emojipanel": 340 | winextra("Emoji") 341 | 342 | if data['actionId'] == "KillerBOSS.TP.Plugins.winextra.keyboard": 343 | winextra("Keyboard") 344 | 345 | if data['actionId'] == "KillerBOSS.TP.Plugins.winsettings.action": 346 | windowsSettings(data['data'][0]['value']) 347 | 348 | @TPClient.on(TouchPortalAPI.TYPES.onHold_down) 349 | def heldingButton(data): 350 | print(data) 351 | while True: 352 | if TPClient.isActionBeingHeld('KillerBOSS.TP.Plugins.AdvanceMouse.MouseClick'): 353 | pyautogui.click(clicks=int(data['data'][0]['value']), button=(data['data'][2]['value']).lower(), interval=float(data['data'][1]['value'])) 354 | elif TPClient.isActionBeingHeld('KillerBOSS.TP.Plugins.AdvanceMouse.Function'): 355 | try: 356 | pyautogui.move(int(data['data'][0]['value']), int(data['data'][1]['value'])) 357 | except Exception: 358 | pass 359 | elif TPClient.isActionBeingHeld('KillerBOSS.TP.Plugins.VolumeMixer.Increase/DecreaseVolume'): 360 | if data['data'][1]['value'] == "Decrease": 361 | audioController.volumeChanger(data['data'][0]['value'], 'Decrease', data['data'][2]['value']) 362 | sleep(0.05) 363 | elif data['data'][1]['value'] == "Increase": 364 | audioController.volumeChanger(data['data'][0]['value'], 'Increase', data['data'][2]['value']) 365 | sleep(0.05) 366 | elif TPClient.isActionBeingHeld('KillerBOSS.TP.Plugins.magnifier.onHold.actions'): 367 | if data['data'][0]['value'] == "Lens X": 368 | magnifer_dimensions(x=True, y=None, onhold=int(data['data'][1]['value'])) 369 | sleep(0.05) 370 | if data['data'][0]['value'] == "Lens Y": 371 | print("uh hi?") 372 | magnifer_dimensions(x=False, y=True, onhold=int(data['data'][1]['value'])) 373 | sleep(0.05) 374 | if data['data'][0]['value'] == "Zoom": 375 | mag_level(int(data['data'][1]['value']), onhold=True) 376 | sleep(0.05) 377 | # elif TPClient.isActionBeingHeld('KillerBOSS.TP.Plugins.winsettings.active.mouseCapture'): # Do we really need this? 378 | # if not cap_live: 379 | # img=capture_around_mouse(int(data['data'][1]['value']),int(data['data'][2]['value'])) 380 | # TPClient.stateUpdate(stateId="KillerBOSS.TP.Plugins.winsettings.active.mouseCapture", stateValue=getFrame_base64(img).decode()) 381 | # sleep(0.07) 382 | # else: 383 | # print("Attempted PUSH + HOLD CAP, but Capture is already live") 384 | # sleep(0.35) 385 | else: 386 | break 387 | 388 | @TPClient.on(TYPES.onConnectorChange) 389 | def connectors(data): 390 | if data['connectorId'] == "KillerBOSS.TP.Plugins.VolumeMixer.connectors.APPcontrol": 391 | if data['data'][0]['value'] == "Master Volume" : 392 | audioController.setMasterVolume(data['value']) 393 | elif data['data'][0]['value'] == "Current app": 394 | activeWindow = getActiveExecutablePath() 395 | # print(activeWindow) 396 | if activeWindow != "": 397 | audioController.volumeChanger(os.path.basename(activeWindow), "Set", data['value']) 398 | else: 399 | try: 400 | audioController.volumeChanger(data['data'][0]['value'], "Set", data['value']) 401 | except: 402 | pass 403 | 404 | if data['connectorId'] == "KillerBOSS.TP.Plugins.Magnifier.connectors.ZoomControl": 405 | if data['data'][0]['value'] == "Zoom" : 406 | mag_level(data['value']*16) 407 | 408 | if data['data'][0]['value'] == "Lens X" : 409 | magnifer_dimensions(x=data['value']) 410 | 411 | if data['data'][0]['value'] == "Lens Y" : 412 | magnifer_dimensions(y=data['value']) 413 | 414 | def updateDeviceOutput(options): 415 | from utils.util import AudioDeviceCmdlets 416 | output = AudioDeviceCmdlets('Get-AudioDevice -List | ConvertTo-Json') 417 | outPutDevice = [] 418 | inputDevice = [] 419 | for x in output: 420 | if x['Type'] == "Playback": 421 | outPutDevice.append(x['Name']) 422 | elif x['Type'] == "Recording": 423 | inputDevice.append(x['Name']) 424 | 425 | if options == "Output": 426 | TPClient.choiceUpdate('KillerBOSS.TP.Plugins.ChangeAudioOutput.Device', outPutDevice) 427 | print('updating Output', outPutDevice) 428 | elif options == "Input": 429 | TPClient.choiceUpdate('KillerBOSS.TP.Plugins.ChangeAudioOutput.Device', inputDevice) 430 | print('updating input', outPutDevice) 431 | 432 | @TPClient.on(TYPES.onListChange) 433 | def listChangeAction(data): 434 | print(data) 435 | global oldcursors 436 | if data['actionId'] == 'KillerBOSS.TP.Plugins.ChangeAudioOutput': 437 | try: 438 | updateDeviceOutput(data['value']) 439 | except KeyError: 440 | pass 441 | if data['actionId'] == 'KillerBOSS.TP.Plugins.virtualdesktop.actions.move_window': 442 | vd_check() 443 | 444 | try: 445 | TPClient.connect() # blocking 446 | except KeyboardInterrupt: 447 | print("Caught keyboard interrupt, exiting.") 448 | except Exception: 449 | from traceback import format_exc 450 | print(f"Exception in TP Client:\n{format_exc()}") 451 | finally: 452 | running = False 453 | TPClient.disconnect() # make sure it's stopped, no-op if already stopped. -------------------------------------------------------------------------------- /new_src/audioMeter.py: -------------------------------------------------------------------------------- 1 | import soundmeter 2 | from math import * 3 | 4 | def root_mean_square(): 5 | current_rms = 0 6 | # DO SOME STUFF 7 | return current_rms 8 | 9 | 10 | def decibel_a(): 11 | current_dba = log(20, 10) * (root_mean_square() / 20) 12 | return current_dba 13 | 14 | print(decibel_a()) -------------------------------------------------------------------------------- /new_src/entry.tp: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": 6, 3 | "version": 231, 4 | "name": "Windows-Tools", 5 | "id": "Windows-Tools", 6 | "configuration": { 7 | "colorDark": "#6c6f73", 8 | "colorLight": "#3d62ad" 9 | }, 10 | "settings": [ 11 | { 12 | "name": "Update Interval: Public IP", 13 | "type": "number", 14 | "default": "240", 15 | "maxValue": 1800, 16 | "minValue": 0, 17 | "allowDecimals": false, 18 | "readOnly": false 19 | }, 20 | { 21 | "name": "Update Interval: Hard Drive", 22 | "type": "number", 23 | "default": "60", 24 | "maxValue": 1800, 25 | "minValue": 0, 26 | "allowDecimals": false, 27 | "readOnly": false 28 | }, 29 | { 30 | "name": "Update Interval: Active Monitors", 31 | "type": "number", 32 | "default": "240", 33 | "maxValue": 1800, 34 | "minValue": 0, 35 | "allowDecimals": false, 36 | "readOnly": false 37 | }, 38 | { 39 | "name": "Update Interval: Active Windows", 40 | "type": "number", 41 | "default": "10", 42 | "maxValue": 1800, 43 | "minValue": 5, 44 | "allowDecimals": false, 45 | "readOnly": false 46 | }, 47 | { 48 | "name": "Update Interval: Active Virtual Desktops", 49 | "type": "number", 50 | "default": "15", 51 | "maxValue": 1800, 52 | "minValue": 5, 53 | "allowDecimals": false, 54 | "readOnly": false 55 | }, 56 | { 57 | "name": "Clipboard Listener (ON / OFF)", 58 | "type": "text", 59 | "default": "ON", 60 | "readOnly": false 61 | }, 62 | { 63 | "name": "Audio State Exemption List", 64 | "type": "text", 65 | "default": "Enter '.exe' name seperated by a comma for more than 1", 66 | "readOnly": false 67 | }, 68 | { 69 | "name": "DEBUG MODE / LOGGING", 70 | "type": "text", 71 | "description": "Wish we could write descript here", 72 | "default": "OFF", 73 | "readOnly": false 74 | } 75 | ], 76 | "plugin_start_cmd": "%TP_PLUGIN_FOLDER%WinTools\\WinTools.exe", 77 | "categories": [ 78 | { 79 | "id": "main", 80 | "name": "Windows-Tool", 81 | "imagepath": "%TP_PLUGIN_FOLDER%WinTools\\icon.png", 82 | "connectors": [ 83 | { 84 | "id": "KillerBOSS.TP.Plugins.VolumeMixer.connectors.APPcontrol", 85 | "name": "APP Volume slider", 86 | "format": "Control volume for {$KillerBOSS.TP.Plugins.VolumeMixer.slidercontrol$}", 87 | "data": [ 88 | { 89 | "id": "KillerBOSS.TP.Plugins.VolumeMixer.slidercontrol", 90 | "type": "choice", 91 | "label": "choice", 92 | "default": "", 93 | "valueChoices": [] 94 | } 95 | ] 96 | }, 97 | { 98 | "id": "KillerBOSS.TP.Plugins.Magnifier.connectors.ZoomControl", 99 | "name": "Magnify Zoom Slider", 100 | "format": "Adjust Magnifier: {$KillerBOSS.TP.Plugins.Magnifier.ZoomControl$}", 101 | "data": [ 102 | { 103 | "id": "KillerBOSS.TP.Plugins.Magnifier.ZoomControl", 104 | "description": "Manually adjust Lens Size and Zoom", 105 | "type": "choice", 106 | "label": "choice", 107 | "default": "", 108 | "valueChoices": ["Zoom", "Lens X", "Lens Y"] 109 | } 110 | ] 111 | } 112 | 113 | ], 114 | "actions": [ 115 | { 116 | "id": "KillerBOSS.TP.Plugins.VolumeMixer.Mute/Unmute", 117 | "name": "Volume Mixer: Mute/Unmute process volume", 118 | "prefix": "plugin", 119 | "type": "communicate", 120 | "tryInline": true, 121 | "format": "{$KillerBOSS.TP.Plugins.VolumeMixer.Mute/Unmute.Choice$} Program:{$KillerBOSS.TP.Plugins.VolumeMixer.Mute/Unmute.process$}", 122 | "data": [ 123 | { 124 | "id": "KillerBOSS.TP.Plugins.VolumeMixer.Mute/Unmute.process", 125 | "type": "choice", 126 | "label": "choice", 127 | "default": "", 128 | "valueChoices": [] 129 | }, 130 | { 131 | "id": "KillerBOSS.TP.Plugins.VolumeMixer.Mute/Unmute.Choice", 132 | "type": "choice", 133 | "label": "choice", 134 | "default": "Mute", 135 | "valueChoices": [ 136 | "Mute", 137 | "Unmute" 138 | ] 139 | } 140 | ] 141 | }, 142 | { 143 | "id": "KillerBOSS.TP.Plugins.VolumeMixer.Increase/DecreaseVolume", 144 | "name": "Volume Mixer: Increase/Decrease process volume", 145 | "prefix": "plugin", 146 | "type": "communicate", 147 | "tryInline": true, 148 | "format": "{$KillerBOSS.TP.Plugins.VolumeMixer.Increase/DecreaseVolume.Ince/DecreChoice$}{$KillerBOSS.TP.Plugins.VolumeMixer.Increase/DecreaseVolume.process$}Volume to {$KillerBOSS.TP.Plugins.VolumeMixer.Increase/DecreaseVolume.Volume$}", 149 | "hasHoldFunctionality": true, 150 | "data": [ 151 | { 152 | "id": "KillerBOSS.TP.Plugins.VolumeMixer.Increase/DecreaseVolume.process", 153 | "type": "choice", 154 | "label": "choice", 155 | "default": "", 156 | "valueChoices": [] 157 | }, 158 | { 159 | "id": "KillerBOSS.TP.Plugins.VolumeMixer.Increase/DecreaseVolume.Ince/DecreChoice", 160 | "type": "choice", 161 | "label": "choice", 162 | "default": "Increase", 163 | "valueChoices": [ 164 | "Increase", 165 | "Decrease", 166 | "Set" 167 | ] 168 | }, 169 | { 170 | "id": "KillerBOSS.TP.Plugins.VolumeMixer.Increase/DecreaseVolume.Volume", 171 | "type": "number", 172 | "label": "choice", 173 | "allowDecimals": false, 174 | "minValue": 0, 175 | "maxValue": 100, 176 | "default": 10 177 | } 178 | ] 179 | }, 180 | { 181 | "id": "KillerBOSS.TP.Plugins.ChangeAudioOutput", 182 | "name": "Sound: Change Input/Output Device", 183 | "prefix": "plugin", 184 | "type": "communicate", 185 | "tryInline": true, 186 | "format": "Change Audio{$KillerBOSS.TP.Plugins.ChangeAudioOutput.Choice$} to Device{$KillerBOSS.TP.Plugins.ChangeAudioOutput.Device$}", 187 | "data": [ 188 | { 189 | "id": "KillerBOSS.TP.Plugins.ChangeAudioOutput.Choice", 190 | "type": "choice", 191 | "label": "choice", 192 | "default": "Pick One", 193 | "valueChoices": [ 194 | "Output", 195 | "Input" 196 | ] 197 | }, 198 | { 199 | "id": "KillerBOSS.TP.Plugins.ChangeAudioOutput.Device", 200 | "type": "choice", 201 | "label": "choice", 202 | "default": "", 203 | "valueChoices": [] 204 | } 205 | ] 206 | }, 207 | { 208 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.HoldDownToggle", 209 | "name": "Mouse: Toggle Mouse Down/Up", 210 | "prefix": "plugin", 211 | "type": "communicate", 212 | "tryInline": true, 213 | "format": "Mouse: Set Mouse Statement to Mouse{$KillerBOSS.TP.Plugins.AdvanceMouse.HoldDownToggle.Toggle$} on {$KillerBOSS.TP.Plugins.AdvanceMouse.HoldDownToggle.ButtonPick$}Button", 214 | "data": [ 215 | { 216 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.HoldDownToggle.Toggle", 217 | "type": "choice", 218 | "label": "choice", 219 | "default": "Down", 220 | "valueChoices": [ 221 | "Down", 222 | "Up" 223 | ] 224 | }, 225 | { 226 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.HoldDownToggle.ButtonPick", 227 | "type": "choice", 228 | "label": "choice", 229 | "default": "Left", 230 | "valueChoices": [ 231 | "Left", 232 | "middle", 233 | "Right" 234 | ] 235 | } 236 | ] 237 | }, 238 | { 239 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.scroll", 240 | "name": "Mouse: Mouse scroll", 241 | "prefix": "plugin", 242 | "type": "communicate", 243 | "tryInline": true, 244 | "hasHoldFunctionality": true, 245 | "format": "Mouse: Scroll {$KillerBOSS.TP.Plugins.AdvanceMouse.scroll.choices$} at {$KillerBOSS.TP.Plugins.AdvanceMouse.scroll.XSpeed$}", 246 | "data": [ 247 | { 248 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.scroll.choices", 249 | "type": "choice", 250 | "label": "scroll option", 251 | "default": "OFF", 252 | "valueChoices": [ 253 | "TOP", 254 | "DOWN", 255 | "LEFT", 256 | "RIGHT" 257 | ] 258 | }, 259 | { 260 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.scroll.XSpeed", 261 | "type": "number", 262 | "label": "number", 263 | "default": 10, 264 | "allowDecimals": false 265 | } 266 | ] 267 | }, 268 | { 269 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.Function", 270 | "name": "Mouse: Move Mouse X, Y", 271 | "prefix": "plugin", 272 | "type": "communicate", 273 | "tryInline": true, 274 | "hasHoldFunctionality": true, 275 | "format": "Increase Mouse X:{$KillerBOSS.TP.Plugins.AdvanceMouse.Function.X$} Y:{$KillerBOSS.TP.Plugins.AdvanceMouse.Function.Y$}", 276 | "data": [ 277 | { 278 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.Function.X", 279 | "type": "number", 280 | "label": "number", 281 | "default": 10, 282 | "allowDecimals": false 283 | }, 284 | { 285 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.Function.Y", 286 | "type": "number", 287 | "label": "number", 288 | "default": 10, 289 | "allowDecimals": false 290 | } 291 | ] 292 | }, 293 | { 294 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.teleport", 295 | "name": "Mouse: Teleport Mouse X, Y with delay, animation", 296 | "prefix": "plugin", 297 | "type": "communicate", 298 | "tryInline": true, 299 | "format": "Mouse: Teleport Mouse to X:{$KillerBOSS.TP.Plugins.AdvanceMouse.teleport.X$} Y:{$KillerBOSS.TP.Plugins.AdvanceMouse.teleport.Y$} with animation Type:{$KillerBOSS.TP.Plugins.AdvanceMouse.teleport.animation$} with speed:{$KillerBOSS.TP.Plugins.AdvanceMouse.teleport.Speed$}", 300 | "data": [ 301 | { 302 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.teleport.X", 303 | "type": "number", 304 | "label": "number", 305 | "default": 10, 306 | "allowDecimals": false 307 | }, 308 | { 309 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.teleport.Y", 310 | "type": "number", 311 | "label": "number", 312 | "default": 10, 313 | "allowDecimals": false 314 | }, 315 | { 316 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.teleport.animation", 317 | "type": "choice", 318 | "label": "choice", 319 | "default": "None", 320 | "valueChoices": [ 321 | "Start slow, end fast", 322 | "Start fast, end slow", 323 | "Start and end fast, slow in middle", 324 | "bounce at the end", 325 | "rubber band at the end", 326 | "None" 327 | ] 328 | }, 329 | { 330 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.teleport.Speed", 331 | "type": "number", 332 | "label": "number", 333 | "default": 10, 334 | "allowDecimals": false 335 | } 336 | ] 337 | }, 338 | { 339 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.MouseClick", 340 | "name": "Mouse: Advanced Mouse Click", 341 | "prefix": "plugin", 342 | "type": "communicate", 343 | "tryInline": true, 344 | "hasHoldFunctionality": true, 345 | "format": "Mouse: Click {$KillerBOSS.TP.Plugins.AdvanceMouse.MouseClick.Times$}Times with delay in between{$KillerBOSS.TP.Plugins.AdvanceMouse.MouseClick.delay$}Seconds with Mouse Key:{$KillerBOSS.TP.Plugins.AdvanceMouse.MouseClick.ButtonPick$}", 346 | "data": [ 347 | { 348 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.MouseClick.Times", 349 | "type": "number", 350 | "label": "number", 351 | "default": 1, 352 | "maxValue": 50, 353 | "minValue": 1, 354 | "allowDecimals": false 355 | }, 356 | { 357 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.MouseClick.delay", 358 | "type": "number", 359 | "label": "number", 360 | "default": 0, 361 | "maxValue": 60, 362 | "minValue": 0, 363 | "allowDecimals": true 364 | }, 365 | { 366 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.MouseClick.ButtonPick", 367 | "type": "choice", 368 | "label": "choice", 369 | "default": "Left", 370 | "valueChoices": [ 371 | "Left", 372 | "Right" 373 | ] 374 | } 375 | ] 376 | }, 377 | { 378 | "id": "KillerBOSS.TP.Plugins.winsettings.active.mouseCapture", 379 | "name": "Mouse: Capture Mouse To Live Icon", 380 | "prefix": "plugin", 381 | "type": "communicate", 382 | "tryInline": true, 383 | "hasHoldFunctionality": true, 384 | "description": "Capture an area around your mouse and project to an icon.", 385 | "format": "Switch Live Mouse Capture :{$KillerBOSS.TP.Plugins.winsettings.active.mouseCapture.Switch$} -> X:{$KillerBOSS.TP.Plugins.winsettings.active.mouseCapture.xSize$} Y:{$KillerBOSS.TP.Plugins.winsettings.active.mouseCapture.ySize$} - Overlay: {$KillerBOSS.TP.Plugins.winsettings.active.mouseCapture.overlay_file$}", 386 | "data": [ 387 | { 388 | "id": "KillerBOSS.TP.Plugins.winsettings.active.mouseCapture.Switch", 389 | "type": "choice", 390 | "label": "choice", 391 | "default": "OFF", 392 | "valueChoices": ["ON", "OFF"] 393 | }, 394 | { 395 | "id": "KillerBOSS.TP.Plugins.winsettings.active.mouseCapture.xSize", 396 | "type": "number", 397 | "label": "number", 398 | "allowDecimals": false, 399 | "default": "300" 400 | }, 401 | { 402 | "id": "KillerBOSS.TP.Plugins.winsettings.active.mouseCapture.ySize", 403 | "type": "number", 404 | "label": "number", 405 | "allowDecimals": false, 406 | "default": "300" 407 | }, 408 | { 409 | "id": "KillerBOSS.TP.Plugins.winsettings.active.mouseCapture.overlay_file", 410 | "type": "choice", 411 | "label": "cursor choices", 412 | "default": "", 413 | "valueChoices": ["None", "LOAD MORE"] 414 | } 415 | ] 416 | }, 417 | { 418 | "id": "KillerBOSS.TP.Plugins.screencapture.full.file", 419 | "name": "CAPTURE: Display to File / Clipboard", 420 | "prefix": "plugin", 421 | "type": "communicate", 422 | "tryInline": true, 423 | "description": "Capture Display to Clipboard OR File", 424 | "format": "Display #{$KillerBOSS.TP.Plugins.screencapture.monitors$} to {$KillerBOSS.TP.Plugins.screencapture.window_active_capture$} and {$KillerBOSS.TP.Plugins.screencapture.filepath$} and {$KillerBOSS.TP.Plugins.screencapture.filename$}", 425 | "data": [ 426 | { 427 | "id": "KillerBOSS.TP.Plugins.screencapture.monitors", 428 | "type": "choice", 429 | "label": "choice", 430 | "default": "", 431 | "valueChoices": [] 432 | }, 433 | { 434 | "id": "KillerBOSS.TP.Plugins.screencapture.window_active_capture", 435 | "type": "choice", 436 | "label": "choice", 437 | "default": "Pick One", 438 | "valueChoices": [ 439 | "Clipboard", 440 | "File" 441 | ] 442 | }, 443 | { 444 | "id": "KillerBOSS.TP.Plugins.screencapture.filepath", 445 | "type": "folder", 446 | "label": "folder" 447 | }, 448 | { 449 | "id": "KillerBOSS.TP.Plugins.screencapture.filename", 450 | "type": "text", 451 | "label": "text", 452 | "default": "" 453 | } 454 | ] 455 | }, 456 | { 457 | "id": "KillerBOSS.TP.Plugins.screencapture.window.file", 458 | "name": "CAPTURE: Window to File / Clipboard", 459 | "prefix": "plugin", 460 | "type": "communicate", 461 | "tryInline": true, 462 | "description": "Capture Window to Clipboard OR File", 463 | "format": "Window:{$KillerBOSS.TP.Plugins.screencapture.window_name$} Save:{$KillerBOSS.TP.Plugins.screencapture.window_active_capture$} Directory->{$KillerBOSS.TP.Plugins.screencapture.filepath$} and file name ->{$KillerBOSS.TP.Plugins.screencapture.filename$} ", 464 | "data": [ 465 | { 466 | "id": "KillerBOSS.TP.Plugins.screencapture.window_name", 467 | "type": "choice", 468 | "label": "choice", 469 | "default": "", 470 | "valueChoices": [] 471 | }, 472 | { 473 | "id": "KillerBOSS.TP.Plugins.screencapture.window_capture_type", 474 | "type": "choice", 475 | "label": "choice", 476 | "default": "3", 477 | "valueChoices": [ 478 | "0", 479 | "1", 480 | "2", 481 | "3" 482 | ] 483 | }, 484 | { 485 | "id": "KillerBOSS.TP.Plugins.screencapture.filepath", 486 | "type": "folder", 487 | "label": "folder", 488 | "default": "" 489 | }, 490 | { 491 | "id": "KillerBOSS.TP.Plugins.screencapture.filename", 492 | "type": "text", 493 | "label": "text", 494 | "default": "" 495 | }, 496 | { 497 | "id": "KillerBOSS.TP.Plugins.screencapture.window_active_capture", 498 | "type": "choice", 499 | "label": "choice", 500 | "default": "Pick One", 501 | "valueChoices": [ 502 | "Clipboard", 503 | "File" 504 | ] 505 | } 506 | ] 507 | }, 508 | { 509 | "id": "KillerBOSS.TP.Plugins.screencapture.window.file.wildcard", 510 | "name": "CAPTURE: Window to File / Clipboard (*)", 511 | "prefix": "plugin", 512 | "type": "communicate", 513 | "tryInline": true, 514 | "description": "Capture Window by Name to Clipboard OR File ", 515 | "format": "Window Name*:{$KillerBOSS.TP.Plugins.screencapture.window_name$} Save:{$KillerBOSS.TP.Plugins.screencapture.window_active_capture$} Directory->{$KillerBOSS.TP.Plugins.screencapture.filepath$} and file name ->{$KillerBOSS.TP.Plugins.screencapture.filename$} ", 516 | "data": [ 517 | { 518 | "id": "KillerBOSS.TP.Plugins.screencapture.window_name", 519 | "type": "text", 520 | "label": "text", 521 | "default": "" 522 | }, 523 | { 524 | "id": "KillerBOSS.TP.Plugins.screencapture.window_capture_type", 525 | "type": "choice", 526 | "label": "choice", 527 | "default": "3", 528 | "valueChoices": [ 529 | "0", 530 | "1", 531 | "2", 532 | "3" 533 | ] 534 | }, 535 | { 536 | "id": "KillerBOSS.TP.Plugins.screencapture.filepath", 537 | "type": "folder", 538 | "label": "folder", 539 | "default": "" 540 | }, 541 | { 542 | "id": "KillerBOSS.TP.Plugins.screencapture.filename", 543 | "type": "text", 544 | "label": "text", 545 | "default": "" 546 | }, 547 | { 548 | "id": "KillerBOSS.TP.Plugins.screencapture.window_active_capture", 549 | "type": "choice", 550 | "label": "choice", 551 | "default": "Pick One", 552 | "valueChoices": [ 553 | "Clipboard", 554 | "File" 555 | ] 556 | } 557 | ] 558 | }, 559 | { 560 | "id": "KillerBOSS.TP.Plugins.window.current", 561 | "name": "CAPTURE: Current Active Window to File / Clipboard", 562 | "prefix": "plugin", 563 | "type": "communicate", 564 | "tryInline": true, 565 | "description": "Capture CURRENT Active Window to Clipboard OR File ", 566 | "format": "Save to {$KillerBOSS.TP.Plugins.screencapture.window_active_capture$} IF file -> {$KillerBOSS.TP.Plugins.screencapture.filepath2$} and {$KillerBOSS.TP.Plugins.screencapture.filename2$}.png", 567 | "data": [ 568 | { 569 | "id": "KillerBOSS.TP.Plugins.screencapture.window_active_capture", 570 | "type": "choice", 571 | "label": "choice", 572 | "default": "Pick One", 573 | "valueChoices": [ 574 | "Clipboard", 575 | "File" 576 | ] 577 | }, 578 | { 579 | "id": "KillerBOSS.TP.Plugins.screencapture.filepath2", 580 | "type": "folder", 581 | "label": "folder", 582 | "default": "" 583 | }, 584 | { 585 | "id": "KillerBOSS.TP.Plugins.screencapture.filename2", 586 | "type": "text", 587 | "label": "text", 588 | "default": "" 589 | } 590 | ] 591 | }, 592 | 593 | { 594 | "id": "KillerBOSS.TP.Plugins.winsettings.move_window", 595 | "name": "DISPLAY: Move Current To Monitor Left/Right", 596 | "prefix": "plugin", 597 | "type": "communicate", 598 | "tryInline": true, 599 | "format": "Move Current Window {$KillerBOSS.TP.Plugins.winsettings.move_window_choice$}", 600 | "data": [ 601 | { 602 | "id": "KillerBOSS.TP.Plugins.winsettings.move_window_choice", 603 | "type": "choice", 604 | "label": "choice", 605 | "default": "Pick a Monitor", 606 | "valueChoices": ["Left", "Right"] 607 | } 608 | ] 609 | }, 610 | 611 | { 612 | "id": "KillerBOSS.TP.Plugins.winsettings.primary_monitor", 613 | "name": "DISPLAY: Change Primary Monitor", 614 | "prefix": "plugin", 615 | "type": "communicate", 616 | "tryInline": true, 617 | "format": "Change Primary Monitor To {$KillerBOSS.TP.Plugins.winsettings.primary_monitor_choice$}", 618 | "data": [ 619 | { 620 | "id": "KillerBOSS.TP.Plugins.winsettings.primary_monitor_choice", 621 | "type": "choice", 622 | "label": "primary monitor choice", 623 | "default": "", 624 | "valueChoices": [] 625 | } 626 | ] 627 | }, 628 | 629 | 630 | { 631 | "id": "KillerBOSS.TP.Plugins.winsettings.rotate_display", 632 | "name": "DISPLAY: Rotate Display / Monitor", 633 | "prefix": "plugin", 634 | "type": "communicate", 635 | "tryInline": true, 636 | "format": "Set Monitor {$KillerBOSS.TP.Plugins.winsettings.monchoice$} to {$KillerBOSS.TP.Plugins.winsettings.mon_rotate$} degrees", 637 | "data": [ 638 | { 639 | "id": "KillerBOSS.TP.Plugins.winsettings.monchoice", 640 | "type": "choice", 641 | "label": "choice", 642 | "default": "Pick a Monitor", 643 | "valueChoices": [] 644 | }, 645 | { 646 | "id": "KillerBOSS.TP.Plugins.winsettings.mon_rotate", 647 | "type": "choice", 648 | "label": "choice", 649 | "default": "0", 650 | "valueChoices": ["0", "90", "180", "270"] 651 | } 652 | ] 653 | }, 654 | { 655 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.actions", 656 | "name": "DISPLAY: Virtual Desktop: Switch/Change", 657 | "prefix": "plugin", 658 | "type": "communicate", 659 | "tryInline": true, 660 | "format": "Go to {$KillerBOSS.TP.Plugins.virtualdesktop.actionchoice$} Virtual Desktop", 661 | "data": [ 662 | { 663 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.actionchoice", 664 | "type": "choice", 665 | "label": "choice", 666 | "default": "", 667 | "valueChoices": [ 668 | "Next", 669 | "Previous" 670 | ] 671 | } 672 | ] 673 | }, 674 | { 675 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.create", 676 | "name": "DISPLAY: Virtual Desktop: Create New", 677 | "prefix": "plugin", 678 | "type": "communicate", 679 | "tryInline": true, 680 | "format": "Create Virtual Desktop with name {$KillerBOSS.TP.Plugins.virtualdesktop.create.name$}", 681 | "data": [ 682 | { 683 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.create.name", 684 | "type": "text", 685 | "label": "text", 686 | "default": "" 687 | } 688 | ] 689 | }, 690 | { 691 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.remove", 692 | "name": "DISPLAY: Virtual Desktop: Remove", 693 | "prefix": "plugin", 694 | "type": "communicate", 695 | "tryInline": true, 696 | "format": "Remove Virtual Desktop {$KillerBOSS.TP.Plugins.virtualdesktop.actionchoice$}", 697 | "data": [ 698 | { 699 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.actionchoice", 700 | "type": "choice", 701 | "label": "choice", 702 | "default": "", 703 | "valueChoices": [] 704 | }, 705 | { 706 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.remove.fallback", 707 | "type": "choice", 708 | "label": "Fall Back Choice", 709 | "default": "", 710 | "valueChoices": [] 711 | } 712 | ] 713 | }, 714 | { 715 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.rename", 716 | "name": "DISPLAY: Virtual Desktop: Rename", 717 | "prefix": "plugin", 718 | "type": "communicate", 719 | "tryInline": true, 720 | "format": "Rename {$KillerBOSS.TP.Plugins.virtualdesktop.actionchoice$} with name {$KillerBOSS.TP.Plugins.virtualdesktop.create.rename$}", 721 | "data": [ 722 | { 723 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.create.rename", 724 | "type": "text", 725 | "label": "text", 726 | "default": "" 727 | }, 728 | { 729 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.actionchoice", 730 | "type": "choice", 731 | "label": "choice", 732 | "default": "", 733 | "valueChoices": [] 734 | } 735 | ] 736 | }, 737 | { 738 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.actions.move_window", 739 | "name": "DISPLAY: Virtual Desktop: Move Current to #", 740 | "prefix": "plugin", 741 | "type": "communicate", 742 | "tryInline": true, 743 | "description": "Move Current Active Window to Virtual Desktop desired", 744 | "format": "{$KillerBOSS.TP.Plugins.virtualdesktop.actionchoice$} Pin it -> {$KillerBOSS.TP.Plugins.virtualdesktop.actionchoice.pinned$}", 745 | "data": [ 746 | { 747 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.actionchoice", 748 | "type": "choice", 749 | "label": "choice", 750 | "default": "", 751 | "valueChoices": [] 752 | }, 753 | { 754 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.actionchoice.pinned", 755 | "type": "choice", 756 | "label": "choice", 757 | "default": "False", 758 | "valueChoices": [ 759 | "True", 760 | "False" 761 | ] 762 | } 763 | ] 764 | }, 765 | 766 | { 767 | "id": "KillerBOSS.TP.Plugins.winsettings.shutdown", 768 | "name": "UTILITY: Shutdown Computer in (x)", 769 | "prefix": "plugin", 770 | "type": "communicate", 771 | "tryInline": true, 772 | "format": "Shutdown Computer in {$KillerBOSS.TP.Plugins.winsettings.shutdown_minutes$} MINUTES", 773 | "data": [ 774 | { 775 | "id": "KillerBOSS.TP.Plugins.winsettings.shutdown_minutes", 776 | "type": "text", 777 | "label": "text", 778 | "default": "" 779 | } 780 | ] 781 | }, 782 | 783 | { 784 | "id": "KillerBOSS.TP.Plugins.winsettings.powerplan", 785 | "name": "UTILITY: Change Powerplan", 786 | "prefix": "plugin", 787 | "type": "communicate", 788 | "tryInline": true, 789 | "format": "Change Windows Powerplan to {$KillerBOSS.TP.Plugins.winsettings.powerplan_choice$}", 790 | "data": [ 791 | { 792 | "id": "KillerBOSS.TP.Plugins.winsettings.powerplan_choice", 793 | "type": "choice", 794 | "label": "pplan choice", 795 | "default": "", 796 | "valueChoices": [] 797 | } 798 | ] 799 | }, 800 | 801 | { 802 | "id": "KillerBOSS.TP.Plugins.winsettings.action", 803 | "name": "UTILITY: System Settings", 804 | "prefix": "plugin", 805 | "type": "communicate", 806 | "tryInline": true, 807 | "format": "Open: {$KillerBOSS.TP.Plugins.winsettings.choice$} settings section", 808 | "data": [ 809 | { 810 | "id": "KillerBOSS.TP.Plugins.winsettings.choice", 811 | "type": "choice", 812 | "label": "choice", 813 | "default": "SYSTEM: Settings Home Page", 814 | "valueChoices": [] 815 | } 816 | ] 817 | }, 818 | 819 | { 820 | "id": "KillerBOSS.TP.Plugins.toast.create", 821 | "name": "UTILITY: Windows Notification", 822 | "prefix": "plugin", 823 | "type": "communicate", 824 | "tryInline": true, 825 | "description": "Create Windows Notification / Toast", 826 | "format": "Title:{$KillerBOSS.TP.Plugins.toast.title$} Message:{$KillerBOSS.TP.Plugins.toast.message$} Duration:{$KillerBOSS.TP.Plugins.toast.duration$} Icon(optional) {$KillerBOSS.TP.Plugins.toast.iconpath$} Sound:{$KillerBOSS.TP.Plugins.toast.audio$} Button-Text(optional):{$KillerBOSS.TP.Plugins.toast.buttontext$} Button-Link(When Clicked):{$KillerBOSS.TP.Plugins.toast.buttonlink$}", 827 | "data": [ 828 | { 829 | "id": "KillerBOSS.TP.Plugins.toast.title", 830 | "type": "text", 831 | "label": "text", 832 | "default": "" 833 | }, 834 | { 835 | "id": "KillerBOSS.TP.Plugins.toast.message", 836 | "type": "text", 837 | "label": "text", 838 | "default": "" 839 | }, 840 | { 841 | "id": "KillerBOSS.TP.Plugins.toast.duration", 842 | "type": "choice", 843 | "label": "choice", 844 | "default": "Short", 845 | "valueChoices": [ 846 | "Short", 847 | "Long" 848 | ] 849 | }, 850 | { 851 | "id": "KillerBOSS.TP.Plugins.toast.buttontext", 852 | "type": "text", 853 | "label": "text", 854 | "default": "" 855 | }, 856 | { 857 | "id": "KillerBOSS.TP.Plugins.toast.buttonlink", 858 | "type": "text", 859 | "label": "text", 860 | "default": "" 861 | }, 862 | { 863 | "id": "KillerBOSS.TP.Plugins.toast.iconpath", 864 | "type": "file", 865 | "label": "file", 866 | "extensions": ["*.jpg","*.png", "*.ico"], 867 | "default": "" 868 | }, 869 | { 870 | "id": "KillerBOSS.TP.Plugins.toast.audio", 871 | "type": "choice", 872 | "label": "choice", 873 | "default": "Default", 874 | "valueChoices": [ 875 | "Default", 876 | "IM", 877 | "Mail", 878 | "Reminder", 879 | "SMS", 880 | "LoopingAlarm1", 881 | "LoopingAlarm2", 882 | "LoopingAlarm3", 883 | "LoopingAlarm4", 884 | "LoopingAlarm5", 885 | "LoopingAlarm6", 886 | "LoopingAlarm7", 887 | "LoopingAlarm8", 888 | "LoopingCall1", 889 | "LoopingCall2", 890 | "LoopingCall3", 891 | "LoopingCall4", 892 | "LoopingCall5", 893 | "LoopingCall6", 894 | "LoopingCall7", 895 | "LoopingCall8", 896 | "LoopingCall9", 897 | "LoopingCall10", 898 | "Silent" 899 | ] 900 | } 901 | ] 902 | }, 903 | { 904 | "id": "KillerBOSS.TP.Plugins.magnifier.actions", 905 | "name": "UTILITY: Magnifier Glass", 906 | "prefix": "plugin", 907 | "type": "communicate", 908 | "tryInline": true, 909 | "format": "Magnifier Glass: {$KillerBOSS.TP.Plugins.magnifier.actionchoice$} ", 910 | "data": [ 911 | { 912 | "id": "KillerBOSS.TP.Plugins.magnifier.actionchoice", 913 | "type": "choice", 914 | "label": "choice", 915 | "default": "", 916 | "valueChoices": [ 917 | "Zoom In", 918 | "Zoom Out", 919 | "Exit", 920 | "Dock", 921 | "Lens", 922 | "Full Screen", 923 | "Invert Colors" 924 | ] 925 | } 926 | ] 927 | }, 928 | { 929 | "id": "KillerBOSS.TP.Plugins.magnifier.onHold.actions", 930 | "name": "UTILITY: Magnifier Glass Adjustment", 931 | "prefix": "plugin", 932 | "type": "communicate", 933 | "tryInline": true, 934 | "hasHoldFunctionality": true, 935 | "description": "IF ON HOLD -> Increment by X \nIF ON PRESS -> Set to X", 936 | "format": "Select {$KillerBOSS.TP.Plugins.magnifier.lens.choice$} and set/adjust by {$KillerBOSS.TP.Plugins.magnifier.lensIncrement$} ", 937 | "data": [ 938 | { 939 | "id": "KillerBOSS.TP.Plugins.magnifier.lens.choice", 940 | "type": "choice", 941 | "label": "choice", 942 | "default": "", 943 | "valueChoices": [ 944 | "Lens X", 945 | "Lens Y", 946 | "Zoom" 947 | ] 948 | }, 949 | { 950 | "id": "KillerBOSS.TP.Plugins.magnifier.lensIncrement", 951 | "type": "text", 952 | "label": "text", 953 | "allowDecimals": false, 954 | "minValue":5, 955 | "maxValue":1600, 956 | "default": "5" 957 | } 958 | ] 959 | }, 960 | { 961 | "id": "KillerBOSS.TP.Plugins.winextra.keyboard", 962 | "name": "UTILITY: On-Screen Keyboard", 963 | "prefix": "plugin", 964 | "type": "communicate", 965 | "tryInline": true, 966 | "format": "Toggle On-Screen Keyboard", 967 | "data": [ 968 | { 969 | "id": "KillerBOSS.TP.Plugins.winextra.action", 970 | "type": "text", 971 | "label": "text", 972 | "default": "" 973 | } 974 | ] 975 | }, 976 | { 977 | "id": "KillerBOSS.TP.Plugins.winextra.emojipanel", 978 | "name": "UTILITY: Emoji Panel", 979 | "prefix": "plugin", 980 | "type": "communicate", 981 | "tryInline": true, 982 | "format": "Open Emoji Panel" 983 | }, 984 | 985 | { 986 | "id": "KillerBOSS.TP.Plugins.capture.clipboard", 987 | "name": "UTILITY: Text / Value to Clipboard", 988 | "prefix": "plugin", 989 | "type": "communicate", 990 | "tryInline": true, 991 | "format": "Copy {$KillerBOSS.TP.Plugins.capture.clipboard.contents$} to clipboard", 992 | "data": [ 993 | { 994 | "id": "KillerBOSS.TP.Plugins.capture.clipboard.contents", 995 | "type": "text", 996 | "label": "text", 997 | "default": "" 998 | } 999 | ] 1000 | }, 1001 | 1002 | { 1003 | "id": "KillerBOSS.TP.Plugins.capture.clipboard.toValue", 1004 | "name": "UTILITY: Paste Clipboard Contents to Value", 1005 | "prefix": "plugin", 1006 | "type": "communicate", 1007 | "tryInline": true, 1008 | "description": "Usage Notes: Remove Brackets from Value Name EXAMPLE: (${value:AD3_desc} -> AD3_desc", 1009 | "format": "Save Clipboard to value {$KillerBOSS.TP.Plugins.capture.clipboard.contents.toValue$}", 1010 | "data": [ 1011 | { 1012 | "id": "KillerBOSS.TP.Plugins.capture.clipboard.contents.toValue", 1013 | "type": "text", 1014 | "label": "text", 1015 | "default": "" 1016 | } 1017 | ] 1018 | }, 1019 | { 1020 | "id": "KillerBOSS.TP.Plugins.TextToSpeech.speak", 1021 | "name": "UTILITY: Text To Speech: Speak X", 1022 | "prefix": "plugin", 1023 | "type": "communicate", 1024 | "description": "Play Text to Speech thru a specific Audio Output", 1025 | "tryInline": true, 1026 | "format": "Text:{$KillerBOSS.TP.Plugins.TextToSpeech.text$} Voice: {$KillerBOSS.TP.Plugins.TextToSpeech.voices$} Volume:{$KillerBOSS.TP.Plugins.TextToSpeech.volume$} Speech Rate:{$KillerBOSS.TP.Plugins.TextToSpeech.rate$} OUTPUT:{$KillerBOSS.TP.Plugins.TextToSpeech.output$}", 1027 | "data": [ 1028 | { 1029 | "id": "KillerBOSS.TP.Plugins.TextToSpeech.voices", 1030 | "type": "choice", 1031 | "label": "choice", 1032 | "default": "", 1033 | "valueChoices": [] 1034 | }, 1035 | { 1036 | "id": "KillerBOSS.TP.Plugins.TextToSpeech.text", 1037 | "type": "text", 1038 | "label": "text", 1039 | "default": "Hello!" 1040 | }, 1041 | { 1042 | "id": "KillerBOSS.TP.Plugins.TextToSpeech.volume", 1043 | "type": "number", 1044 | "label": "tts volume", 1045 | "allowDecimals": false, 1046 | "default": "100", 1047 | "minValue":0, 1048 | "maxValue":100 1049 | }, 1050 | { 1051 | "id": "KillerBOSS.TP.Plugins.TextToSpeech.rate", 1052 | "type": "number", 1053 | "label": "tts rate", 1054 | "allowDecimals": false, 1055 | "default": "175", 1056 | "minValue":25, 1057 | "maxValue":600 1058 | }, 1059 | { 1060 | "id": "KillerBOSS.TP.Plugins.TextToSpeech.output", 1061 | "type": "choice", 1062 | "label": "tts output choice", 1063 | "default": "", 1064 | "valueChoices":[] 1065 | } 1066 | ] 1067 | }, 1068 | { 1069 | "id": "KillerBOSS.TP.Plugins.TextToSpeech.stop", 1070 | "name": "UTILITY: Text to Speech: Stop", 1071 | "prefix": "plugin", 1072 | "type": "communicate", 1073 | "tryInline": true, 1074 | "format": "Stop TextToSpeech" 1075 | } 1076 | ], 1077 | "events": [ 1078 | { 1079 | "id": "KillerBOSS.TP.Plugins.events.default_outputdevice", 1080 | "name": "When Default Output Device changes", 1081 | "format": "When Default Output Device changes $val", 1082 | "type": "communicate", 1083 | "valueChoices": [ 1084 | "True" 1085 | ], 1086 | "valueType": "choice", 1087 | "valueStateId": "KillerBOSS.TP.Plugins.state.default_outputdevice" 1088 | }, 1089 | { 1090 | "id": "KillerBOSS.TP.Plugins.events.default_inputdevice", 1091 | "name": "When Default Input Device changes", 1092 | "format": "When Default Input Device changes $val", 1093 | "type": "communicate", 1094 | "valueChoices": [ 1095 | "True" 1096 | ], 1097 | "valueType": "choice", 1098 | "valueStateId": "KillerBOSS.TP.Plugins.state.default_inputdevice" 1099 | }, 1100 | { 1101 | "id": "KillerBOSS.TP.Plugins.events.clipboard_contents", 1102 | "name": "When Clipboard Contents Change", 1103 | "format": "When Clipboard Contents Change $val", 1104 | "type": "communicate", 1105 | "valueChoices": [ 1106 | "True" 1107 | ], 1108 | "valueType": "choice", 1109 | "valueStateId": "KillerBOSS.TP.Plugins.capture.clipboard.contents" 1110 | } 1111 | ], 1112 | "states": [ 1113 | { 1114 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.MousePos.X", 1115 | "type": "text", 1116 | "desc": "Advance Mouse: Current Mouse X pos", 1117 | "default": "0" 1118 | }, 1119 | { 1120 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.MousePos.Y", 1121 | "type": "text", 1122 | "desc": "Advance Mouse: Current Mouse Y pos", 1123 | "default": "0" 1124 | }, 1125 | { 1126 | "id": "KillerBOSS.TP.Plugins.winsettings.state.active.mouseCapture", 1127 | "type": "text", 1128 | "desc": "Active Mouse Capture", 1129 | "default": "" 1130 | }, 1131 | { 1132 | "id": "KillerBOSS.TP.Plugins.Sound.CurrentOutputDevice", 1133 | "type": "text", 1134 | "desc": "Sound: Get Current Output Device", 1135 | "default": "None" 1136 | }, 1137 | { 1138 | "id": "KillerBOSS.TP.Plugins.Sound.CurrentInputDevice", 1139 | "type": "text", 1140 | "desc": "Sound: Get Current Input Device", 1141 | "default": "None" 1142 | }, 1143 | { 1144 | "id": "KillerBOSS.TP.Plugins.Application.currentFocusedAPP", 1145 | "type": "text", 1146 | "desc": "Application get current focused APP", 1147 | "default": "None" 1148 | }, 1149 | { 1150 | "id": "KillerBOSS.TP.Plugins.windows.network.received", 1151 | "type": "text", 1152 | "desc": "Network: Total Bytes Received", 1153 | "default": "" 1154 | }, 1155 | { 1156 | "id": "KillerBOSS.TP.Plugins.windows.network.sent", 1157 | "type": "text", 1158 | "desc": "Network: Total Bytes Sent", 1159 | "default": "" 1160 | }, 1161 | { 1162 | "id": "KillerBOSS.TP.Plugins.windows.disk.read", 1163 | "type": "text", 1164 | "desc": "Disk: Total Read", 1165 | "default": "" 1166 | }, 1167 | { 1168 | "id": "KillerBOSS.TP.Plugins.windows.disk.write", 1169 | "type": "text", 1170 | "desc": "Disk: Total Write", 1171 | "default": "" 1172 | }, 1173 | { 1174 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.current_vd", 1175 | "type": "text", 1176 | "desc": "Curent Virtual Desktop", 1177 | "default": "" 1178 | }, 1179 | { 1180 | "id": "KillerBOSS.TP.Plugins.Windows.activeCOUNT", 1181 | "type": "text", 1182 | "desc": "Active Window Count", 1183 | "default": "" 1184 | }, 1185 | { 1186 | "id": "KillerBOSS.TP.Plugins.winsettings.powerplan_current", 1187 | "type": "text", 1188 | "desc": "Active Power Plan", 1189 | "default": "" 1190 | }, 1191 | { 1192 | "id": "KillerBOSS.TP.Plugins.Windows.livetime", 1193 | "type": "text", 1194 | "desc": "Computer Uptime", 1195 | "default": "" 1196 | }, 1197 | { 1198 | "id": "KillerBOSS.TP.Plugins.capture.clipboard.contents", 1199 | "type": "text", 1200 | "desc": "Clipboard Contents", 1201 | "default": "" 1202 | } 1203 | ] 1204 | }, 1205 | { 1206 | "id":"Public IP", 1207 | "name":"Public IP Info", 1208 | "states":[ 1209 | { 1210 | "id":"KillerBOSS.TP.Plugins.publicip.ip", 1211 | "type":"text", 1212 | "desc":"Public IP: IP Address", 1213 | "default":"" 1214 | }, 1215 | { 1216 | "id":"KillerBOSS.TP.Plugins.publicip.city", 1217 | "type":"text", 1218 | "desc":"Pubic IP: City", 1219 | "default":"" 1220 | }, 1221 | { 1222 | "id":"KillerBOSS.TP.Plugins.publicip.country", 1223 | "type":"text", 1224 | "desc":"Public IP: Country", 1225 | "default":"" 1226 | }, 1227 | { 1228 | "id":"KillerBOSS.TP.Plugins.publicip.region", 1229 | "type":"text", 1230 | "desc":"Public IP: Region", 1231 | "default":"" 1232 | }, 1233 | { 1234 | "id":"KillerBOSS.TP.Plugins.publicip.timezone", 1235 | "type":"text", 1236 | "desc":"Pubic IP: Timezone", 1237 | "default":"" 1238 | }, 1239 | { 1240 | "id":"KillerBOSS.TP.Plugins.publicip.organization", 1241 | "type":"text", 1242 | "desc":"Pubic IP: Internet Provider", 1243 | "default":"" 1244 | } 1245 | ] 1246 | } 1247 | ] 1248 | } 1249 | -------------------------------------------------------------------------------- /new_src/utils/TextToSpeech.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import audio2numpy as a2n 4 | import pyttsx3 5 | import sounddevice as sd 6 | from .util import getAllOutput_TTS2, getAllVoices 7 | 8 | 9 | def TextToSpeech(message, voicesChoics, volume=100, rate=100, output="Default"): 10 | engine = pyttsx3.init() 11 | voices = engine.getProperty('voices') 12 | engine.setProperty("volume", volume/100) 13 | engine.setProperty("rate", rate) 14 | for voice in getAllVoices(): 15 | if voice.name == voicesChoics: 16 | engine.setProperty('voice', voice.id) 17 | print("Using", voice.name, "voices", voice) 18 | 19 | if output =="Default": 20 | try: 21 | engine.say(message) 22 | engine.runAndWait() 23 | engine.stop() 24 | except Exception as e: 25 | print("TTS Error", e) 26 | else: 27 | try: 28 | appdata = os.getenv('APPDATA') 29 | engine.save_to_file(message, rf"{appdata}/TouchPortal/Plugins/WinTools/speech.wav") 30 | engine.runAndWait() 31 | engine.stop() 32 | device = getAllOutput_TTS2() ### can make this list returned a global + save that will pull it once and thats it? instead of every time this action is called..which could be troublesome.. 33 | sd.default.samplerate = device[output] 34 | sd.default.device = output +", MME" 35 | x,sr=a2n.audio_from_file(rf"{appdata}/TouchPortal/Plugins/WinTools/speech.wav") 36 | sd.play(x, sr, blocking=True) 37 | except Exception as e: 38 | print("EXCEPTION ERROR(Line:880)", e) -------------------------------------------------------------------------------- /new_src/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KillerBOSS2019/WinTools/d5cbbe721b5ff150e7b3a4afe9dca41a82c31ca5/new_src/utils/__init__.py -------------------------------------------------------------------------------- /new_src/utils/audioController.py: -------------------------------------------------------------------------------- 1 | from ctypes import POINTER, cast 2 | 3 | import pythoncom 4 | from comtypes import CLSCTX_ALL 5 | from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume 6 | 7 | 8 | class AudioController(object): 9 | def __init__(self, process_name): 10 | self.process_name = process_name 11 | self.volume = self.process_volume() 12 | 13 | def process_volume(self): 14 | pythoncom.CoInitialize() # 3rd coinitilize... 15 | sessions = AudioUtilities.GetAllSessions() 16 | for session in sessions: 17 | interface = session.SimpleAudioVolume 18 | if session.Process and session.Process.name() == self.process_name: 19 | # print('Volume:', interface.GetMasterVolume()) # debug 20 | return interface.GetMasterVolume() 21 | 22 | def set_volume(self, decibels): 23 | sessions = AudioUtilities.GetAllSessions() 24 | print(self.process_name) 25 | for session in sessions: 26 | interface = session.SimpleAudioVolume 27 | if session.Process and session.Process.name() == self.process_name: 28 | # only set volume in the range 0.0 to 1.0 29 | self.volume = min(1.0, max(0.0, decibels)) 30 | interface.SetMasterVolume(self.volume, None) 31 | 32 | def decrease_volume(self, decibels): 33 | sessions = AudioUtilities.GetAllSessions() 34 | for session in sessions: 35 | interface = session.SimpleAudioVolume 36 | if session.Process and session.Process.name() == self.process_name: 37 | # 0.0 is the min value, reduce by decibels 38 | self.volume = max(0.0, self.volume-decibels) 39 | interface.SetMasterVolume(self.volume, None) 40 | 41 | def increase_volume(self, decibels): 42 | sessions = AudioUtilities.GetAllSessions() 43 | for session in sessions: 44 | interface = session.SimpleAudioVolume 45 | if session.Process and session.Process.name() == self.process_name: 46 | 47 | # 1.0 is the max value, raise by decibels 48 | self.volume = min(1.0, self.volume+decibels) 49 | interface.SetMasterVolume(self.volume, None) 50 | 51 | 52 | def muteAndUnMute(process, value): 53 | if value == "Mute": 54 | value = 1 55 | elif value == "Unmute": 56 | value = 0 57 | sessions = AudioUtilities.GetAllSessions() 58 | for session in sessions: 59 | volume = session.SimpleAudioVolume 60 | if session.Process and session.Process.name() == process: 61 | volume.SetMute(value, None) 62 | 63 | 64 | def volumeChanger(process, action, value): 65 | if action == "Set": 66 | AudioController(str(process)).set_volume((int(value)*0.01)) 67 | elif action == "Increase": 68 | AudioController(str(process)).increase_volume((int(value)*0.01)) 69 | 70 | elif action == "Decrease": 71 | AudioController(str(process)).decrease_volume((int(value)*0.01)) 72 | 73 | 74 | def setMasterVolume(Vol): 75 | devices = AudioUtilities.GetSpeakers() 76 | interface = devices.Activate( 77 | IAudioEndpointVolume._iid_, CLSCTX_ALL, None) 78 | volume = cast(interface, POINTER(IAudioEndpointVolume)) 79 | scalarVolume = int(Vol) / 100 80 | volume.SetMasterVolumeLevelScalar(scalarVolume, None) 81 | 82 | 83 | def getMasterVolume() -> int: 84 | devices = AudioUtilities.GetSpeakers() 85 | interface = devices.Activate( 86 | IAudioEndpointVolume._iid_, CLSCTX_ALL, None) 87 | volume = cast(interface, POINTER(IAudioEndpointVolume)) 88 | return int(round(volume.GetMasterVolumeLevelScalar() * 100)) 89 | -------------------------------------------------------------------------------- /new_src/utils/audioSwitch.py: -------------------------------------------------------------------------------- 1 | import policyconfig as pc 2 | import comtypes 3 | 4 | def switchSpeaker(switchTo, role): 5 | policy_config = comtypes.CoCreateInstance( 6 | pc.CLSID_PolicyConfigClient, 7 | pc.IPolicyConfig, 8 | comtypes.CLSCTX_ALL 9 | ) 10 | pc.ERole.eCommunications 11 | policy_config.SetDefaultEndpoint(switchTo, role) -------------------------------------------------------------------------------- /new_src/utils/clipboard.py: -------------------------------------------------------------------------------- 1 | import win32clipboard 2 | from io import BytesIO 3 | from PIL import Image 4 | import win32gui 5 | import os 6 | import win32ui 7 | from ctypes import windll 8 | 9 | ##################################################### 10 | # # 11 | # Clipboard stuff # 12 | # # 13 | ###################################################### 14 | 15 | def copy_im_to_clipboard(image): 16 | bio = BytesIO() 17 | image.save(bio, 'BMP') 18 | data = bio.getvalue()[14:] # removing some headers 19 | bio.close() 20 | send_to_clipboard(win32clipboard.CF_DIB, data) 21 | 22 | 23 | def send_to_clipboard(clip_type, data): 24 | if clip_type == "text": 25 | win32clipboard.OpenClipboard() 26 | win32clipboard.EmptyClipboard() 27 | win32clipboard.SetClipboardText(data) 28 | win32clipboard.CloseClipboard() 29 | else: 30 | win32clipboard.OpenClipboard() 31 | win32clipboard.EmptyClipboard() 32 | win32clipboard.SetClipboardData(clip_type, data) 33 | win32clipboard.CloseClipboard() 34 | 35 | def get_clipboard_data(): 36 | try: 37 | win32clipboard.OpenClipboard() 38 | data = win32clipboard.GetClipboardData() 39 | win32clipboard.CloseClipboard() 40 | print("HELLO?") 41 | return data 42 | except TypeError as err: 43 | print("BROKEN") 44 | return "Invalid Clipboard Data" 45 | 46 | 47 | ## Image to Bytes 48 | def file_to_bytes(filepath): 49 | ## Take image into bytes and onto clipboard 50 | image = Image.open(filepath) 51 | output = BytesIO() 52 | image.convert("RGB").save(output, "BMP") 53 | data = output.getvalue()[14:] 54 | output.close() 55 | 56 | ### Sending to Clipboard 57 | send_to_clipboard(win32clipboard.CF_DIB, data) 58 | ### Deleting Temp File 59 | os.remove(filepath) 60 | print("Temp Image Deleted") 61 | 62 | ###screenshot window without bringing it to foreground 63 | def screenshot_window(capture_type, window_title=None, clipboard=False, save_location=None): 64 | hwnd = win32gui.FindWindow(None, window_title) 65 | try: 66 | left, top, right, bot = win32gui.GetClientRect(hwnd) 67 | #left, top, right, bot = win32gui.GetWindowRect(hwnd) 68 | w = right - left 69 | h = bot - top 70 | 71 | hwndDC = win32gui.GetWindowDC(hwnd) 72 | mfcDC = win32ui.CreateDCFromHandle(hwndDC) 73 | saveDC = mfcDC.CreateCompatibleDC() 74 | 75 | saveBitMap = win32ui.CreateBitmap() 76 | saveBitMap.CreateCompatibleBitmap(mfcDC, w, h) 77 | saveDC.SelectObject(saveBitMap) 78 | 79 | # Change the line below depending on whether you want the whole window 80 | # or just the client area as shown above. 81 | # 1, 2, 3 all give different results ( 3 seems to work for everything) 82 | result = windll.user32.PrintWindow(hwnd, saveDC.GetSafeHdc(), capture_type) 83 | bmpinfo = saveBitMap.GetInfo() 84 | bmpstr = saveBitMap.GetBitmapBits(True) 85 | 86 | im = Image.frombuffer( 87 | 'RGB', 88 | (bmpinfo['bmWidth'], bmpinfo['bmHeight']), 89 | bmpstr, 'raw', 'BGRX', 0, 1) 90 | 91 | win32gui.DeleteObject(saveBitMap.GetHandle()) 92 | saveDC.DeleteDC() 93 | mfcDC.DeleteDC() 94 | win32gui.ReleaseDC(hwnd, hwndDC) 95 | 96 | if result == 1: 97 | #PrintWindow Succeeded 98 | if clipboard == True: 99 | copy_im_to_clipboard(im) 100 | print("Copied to Clipboard") 101 | elif clipboard == False: 102 | im.save(save_location+".png") 103 | print("Saved to Folder") 104 | except Exception as e: 105 | print("error screenshot" + e ) -------------------------------------------------------------------------------- /new_src/utils/magnifier.py: -------------------------------------------------------------------------------- 1 | import re 2 | import winreg 3 | from .util import runCommandLine 4 | 5 | 6 | class WindowsRegistry: 7 | """Class WindowsRegistry is using for easy manipulating Windows registry. 8 | Methods 9 | ------- 10 | query_value(full_path : str) 11 | Check value for existing. 12 | get_value(full_path : str) 13 | Get value's data. 14 | set_value(full_path : str, value : str, value_type='REG_SZ' : str) 15 | Create a new value with data or set data to an existing value. 16 | delete_value(full_path : str) 17 | Delete an existing value. 18 | query_key(full_path : str) 19 | Check key for existing. 20 | delete_key(full_path : str) 21 | Delete an existing key(only without subkeys). 22 | Examples: 23 | WindowsRegistry.set_value('HKCU/Software/Microsoft/Windows/CurrentVersion/Run', 'Program', r'"c:\Dir1\program.exe"') 24 | WindowsRegistry.delete_value('HKEY_CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/Run/Program') 25 | """ 26 | @staticmethod 27 | def __parse_data(full_path): 28 | full_path = re.sub(r'/', r'\\', full_path) 29 | hive = re.sub(r'\\.*$', '', full_path) 30 | if not hive: 31 | raise ValueError('Invalid \'full_path\' param.') 32 | if len(hive) <= 4: 33 | if hive == 'HKLM': 34 | hive = 'HKEY_LOCAL_MACHINE' 35 | elif hive == 'HKCU': 36 | hive = 'HKEY_CURRENT_USER' 37 | elif hive == 'HKCR': 38 | hive = 'HKEY_CLASSES_ROOT' 39 | elif hive == 'HKU': 40 | hive = 'HKEY_USERS' 41 | reg_key = re.sub(r'^[A-Z_]*\\', '', full_path) 42 | reg_key = re.sub(r'\\[^\\]+$', '', reg_key) 43 | reg_value = re.sub(r'^.*\\', '', full_path) 44 | 45 | return hive, reg_key, reg_value 46 | 47 | @staticmethod 48 | def query_value(full_path): 49 | value_list = WindowsRegistry.__parse_data(full_path) 50 | try: 51 | opened_key = winreg.OpenKey(getattr(winreg, value_list[0]), value_list[1], 0, winreg.KEY_READ) 52 | winreg.QueryValueEx(opened_key, value_list[2]) 53 | winreg.CloseKey(opened_key) 54 | return True 55 | except WindowsError: 56 | return False 57 | 58 | @staticmethod 59 | def get_value(full_path): 60 | value_list = WindowsRegistry.__parse_data(full_path) 61 | try: 62 | opened_key = winreg.OpenKey(getattr(winreg, value_list[0]), value_list[1], 0, winreg.KEY_READ) 63 | value_of_value, value_type = winreg.QueryValueEx(opened_key, value_list[2]) 64 | winreg.CloseKey(opened_key) 65 | return value_of_value 66 | except WindowsError: 67 | return None 68 | 69 | @staticmethod 70 | def set_value(full_path, value, value_type='REG_SZ'): 71 | value_list = WindowsRegistry.__parse_data(full_path) 72 | try: 73 | winreg.CreateKey(getattr(winreg, value_list[0]), value_list[1]) 74 | opened_key = winreg.OpenKey(getattr(winreg, value_list[0]), value_list[1], 0, winreg.KEY_WRITE) 75 | winreg.SetValueEx(opened_key, value_list[2], 0, getattr(winreg, value_type), value) 76 | winreg.CloseKey(opened_key) 77 | return True 78 | except WindowsError: 79 | return False 80 | 81 | @staticmethod 82 | def query_key(full_path): 83 | value_list = WindowsRegistry.__parse_data(full_path) 84 | try: 85 | opened_key = winreg.OpenKey(getattr(winreg, value_list[0]), value_list[1] + r'\\' + value_list[2], 0, winreg.KEY_READ) 86 | winreg.CloseKey(opened_key) 87 | return True 88 | except WindowsError: 89 | return False 90 | 91 | magpath = r"HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\\" 92 | is_on=WindowsRegistry.get_value(magpath+"\RunningState") 93 | 94 | def mag_on(): 95 | """Check if Magnify is on 96 | - If magnify is off, this turns it on. 97 | Always returns True 98 | """ 99 | is_on=WindowsRegistry.get_value(magpath+"\RunningState") 100 | if is_on: 101 | return True 102 | if not is_on: 103 | runCommandLine('magnify') 104 | return True 105 | 106 | 107 | def mag_mode(mode=3): 108 | """ 109 | - 1 = Docked 110 | - 2 = Full Screen 111 | - 3 = Lens 112 | """ 113 | exists = WindowsRegistry.query_value(magpath + "MagnificationMode") 114 | if exists: 115 | WindowsRegistry.set_value("HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\MagnificationMode", mode, value_type='REG_DWORD') 116 | 117 | 118 | 119 | def mag_invert(): 120 | """ Magnifier Invert 121 | - Toggles On / Off 122 | """ 123 | exists = WindowsRegistry.query_value(magpath + "Invert") 124 | if exists: 125 | current = WindowsRegistry.get_value(magpath + "Invert") 126 | if current == 1: 127 | WindowsRegistry.set_value(r"HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\Invert", 0, value_type='REG_DWORD') 128 | if current ==0: 129 | WindowsRegistry.set_value(r"HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\Invert", 1, value_type='REG_DWORD') 130 | 131 | 132 | def mag_increments(amount): 133 | """Setting Zoom Increments - MAX 400%, MIN 5%""" 134 | exists = WindowsRegistry.query_value(magpath + "ZoomIncrement") 135 | if exists: 136 | if amount: 137 | WindowsRegistry.set_value("HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\ZoomIncrement", amount, value_type='REG_DWORD') 138 | 139 | def mag_level(amount, onhold=False): 140 | """Set Zoom Levels 141 | - 1600 is MAX (overriden to 1000) 142 | - Amount = Zoom Set 143 | - On Hold Amount = Increment Zoom 144 | """ 145 | print("we in..", amount) 146 | themin=20 147 | themax=1000 148 | current = WindowsRegistry.get_value("HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\Magnification") 149 | exists = WindowsRegistry.query_value(magpath + "Magnification") 150 | if not onhold: 151 | if exists: 152 | if amount: 153 | if amount >themax: 154 | mag_on() 155 | WindowsRegistry.set_value(r"HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\Magnification", themax, value_type='REG_DWORD') 156 | else: 157 | mag_on() 158 | WindowsRegistry.set_value(r"HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\Magnification", amount, value_type='REG_DWORD') 159 | if onhold: 160 | if exists: 161 | if current < themin: 162 | print("less than 20") 163 | WindowsRegistry.set_value("HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\Magnification", 20, value_type='REG_DWORD') 164 | elif current > themax: 165 | try: 166 | WindowsRegistry.set_value("HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\Magnification", 1600, value_type='REG_DWORD') 167 | except: 168 | pass 169 | else: 170 | try: 171 | WindowsRegistry.set_value("HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\Magnification", current + amount, value_type='REG_DWORD') 172 | except: 173 | pass 174 | 175 | def text_smoothing(switch): 176 | """Text Smoothing 177 | - Switch = On / Off 178 | """ 179 | exists = WindowsRegistry.query_value(magpath + "UseBitmapSmoothing") 180 | if exists: 181 | if switch =="On": 182 | WindowsRegistry.set_value(r"HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\UseBitmapSmoothing", 1, value_type='REG_DWORD') 183 | elif switch == "Off": 184 | WindowsRegistry.set_value(r"HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\UseBitmapSmoothing", 0, value_type='REG_DWORD') 185 | 186 | 187 | def magnifer_dimensions(x=None, y=None, onhold=False): 188 | """Can set a MIN/MAX Value to avoid this 189 | - onhold = int value increment 190 | """ 191 | exists = WindowsRegistry.query_value(magpath + "LensWidth") 192 | themax=95 193 | themin=20 194 | if not onhold: 195 | if x: 196 | if exists: 197 | WindowsRegistry.set_value("HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\LensWidth", x, value_type='REG_DWORD') 198 | if y: 199 | if exists: 200 | WindowsRegistry.set_value("HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\LensHeight", y, value_type='REG_DWORD') 201 | 202 | if onhold: 203 | if exists: 204 | if x: 205 | current = WindowsRegistry.get_value("HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\LensWidth") 206 | if current < themin: 207 | print("less than 20") 208 | WindowsRegistry.set_value("HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\LensWidth", 20, value_type='REG_DWORD') 209 | elif current > themax: 210 | WindowsRegistry.set_value("HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\LensWidth", 95, value_type='REG_DWORD') 211 | else: 212 | WindowsRegistry.set_value("HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\LensWidth", current + onhold, value_type='REG_DWORD') 213 | if y: 214 | current = WindowsRegistry.get_value("HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\LensHeight") 215 | if current < themin: 216 | print("less than 20") 217 | WindowsRegistry.set_value("HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\LensHeight", 20, value_type='REG_DWORD') 218 | elif current > themax: 219 | WindowsRegistry.set_value("HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\LensHeight", 95, value_type='REG_DWORD') 220 | else: 221 | WindowsRegistry.set_value("HKEY_CURRENT_USER\SOFTWARE\Microsoft\ScreenMagnifier\LensHeight", current + onhold, value_type='REG_DWORD') -------------------------------------------------------------------------------- /new_src/utils/monitorPrimary.py: -------------------------------------------------------------------------------- 1 | import pywintypes 2 | import win32api 3 | 4 | """ DISPLAY CHANGE STUFF """ 5 | #DISPLAY_DEVICE.StateFlags 6 | DISPLAY_DEVICE_ACTIVE = 0x1 7 | DISPLAY_DEVICE_MULTI_DRIVER = 0x2 8 | DISPLAY_DEVICE_PRIMARY_DEVICE = 0x4 9 | DISPLAY_DEVICE_MIRRORING_DRIVER = 0x8 10 | DISPLAY_DEVICE_VGA_COMPATIBLE = 0x10 11 | DISPLAY_DEVICE_REMOVABLE = 0x20 12 | DISPLAY_DEVICE_DISCONNECT = 0x2000000 13 | DISPLAY_DEVICE_REMOTE = 0x4000000 14 | DISPLAY_DEVICE_MODESPRUNED = 0x8000000 15 | 16 | #EnumDisplaySettingsEx.iModeNum 17 | ENUM_CURRENT_SETTINGS = -1 18 | ENUM_REGISTRY_SETTINGS = -2 19 | 20 | #ChangeDisplaySettingsEx.dwflags 21 | CDS_NONE = 0x00000000 22 | CDS_UPDATEREGISTRY = 0x00000001 23 | CDS_TEST = 0x00000002 24 | CDS_FULLSCREEN = 0x00000004 25 | CDS_GLOBAL = 0x00000008 26 | CDS_SET_PRIMARY = 0x00000010 27 | CDS_VIDEOPARAMETERS = 0x00000020 28 | CDS_ENABLE_UNSAFE_MODES = 0x00000100 29 | CDS_DISABLE_UNSAFE_MODES = 0x00000200 30 | CDS_RESET = 0x40000000 31 | CDS_RESET_EX = 0x20000000 32 | CDS_NORESET = 0x10000000 33 | 34 | def change_primary(monitornum): 35 | 36 | monitornum = monitornum.split(":")[0] 37 | primary = rf"\\.\DISPLAY{monitornum}" 38 | print("After splitting", monitornum) 39 | 40 | # Find the settings of the new primary display 41 | i = 0 42 | while True: 43 | try: 44 | device = win32api.EnumDisplayDevices(None, i) 45 | except pywintypes.error: 46 | break 47 | 48 | if device.DeviceName == primary: 49 | primary_settings = win32api.EnumDisplaySettingsEx(device.DeviceName, ENUM_CURRENT_SETTINGS, 0) 50 | break 51 | 52 | i += 1 53 | 54 | # Update all the positions of the displays relative to the new primary display 55 | i = 0 56 | while True: 57 | try: 58 | device = win32api.EnumDisplayDevices(None, i) 59 | except pywintypes.error: 60 | break 61 | 62 | if device.StateFlags & DISPLAY_DEVICE_ACTIVE != 0: 63 | # print (device.DeviceName) 64 | settings = win32api.EnumDisplaySettingsEx(device.DeviceName, ENUM_CURRENT_SETTINGS, 0) 65 | # print (settings.PelsWidth, "x", settings.PelsHeight, "@", settings.Position_x, ",", settings.Position_y) 66 | 67 | settings.Position_x -= primary_settings.Position_x 68 | settings.Position_y -= primary_settings.Position_y 69 | 70 | # CDS_UPDATEREGISTRY | CDS_NORESET = Don't make the changes yet until we've updated all the displays 71 | if device.DeviceName == primary: 72 | win32api.ChangeDisplaySettingsEx(device.DeviceName, settings, CDS_SET_PRIMARY | CDS_UPDATEREGISTRY | CDS_NORESET) 73 | else: 74 | win32api.ChangeDisplaySettingsEx(device.DeviceName, settings, CDS_UPDATEREGISTRY | CDS_NORESET) 75 | 76 | i += 1 77 | 78 | ## Update the displays with the registry settings 79 | win32api.ChangeDisplaySettingsEx(None, None) -------------------------------------------------------------------------------- /new_src/utils/policyconfig.py: -------------------------------------------------------------------------------- 1 | ## This module is in large chunks taken from https://github.com/kdschlosser/pyWinCoreAudio/blob/431d5d9b470083a6a5c51738e08b12009fa315eb/pyWinCoreAudio/__core_audio/policyconfig.py. 2 | ## This requires us to use comtypes alongside pywin32, which is somewhat of a duplication in depedencies. 3 | ## I think we could use pyWinCoreAudio instead of soundcard, but we will still likely need pywin32 for the service. 4 | 5 | 6 | import comtypes, enum 7 | from comtypes import COMMETHOD, GUID 8 | import ctypes 9 | from ctypes import ( 10 | POINTER, 11 | HRESULT, 12 | c_int as enum 13 | ) 14 | 15 | 16 | 17 | from ctypes.wintypes import ( 18 | INT, 19 | BOOL, 20 | LPCWSTR, 21 | WORD 22 | ) 23 | 24 | IID_IPolicyConfig = GUID( 25 | '{f8679f50-850a-41cf-9c72-430f290290c8}' 26 | ) 27 | 28 | CLSID_PolicyConfigClient = GUID( 29 | '{870af99c-171d-4f9e-af0d-e63df40c2bc9}' 30 | ) 31 | 32 | IID_AudioSes = ( 33 | '{00000000-0000-0000-0000-000000000000}' 34 | ) 35 | 36 | ConfigFactory = GUID("2a59116d-6c4f-45e0-a74f-707e3fef9258") 37 | 38 | 39 | REFERENCE_TIME = ctypes.c_longlong 40 | 41 | 42 | LPCGUID = POINTER(GUID) 43 | LPREFERENCE_TIME = POINTER(REFERENCE_TIME) 44 | 45 | class DeviceSharedMode(ctypes.Structure): 46 | _fields_ = [ 47 | ('dummy_', INT) 48 | ] 49 | 50 | 51 | PDeviceSharedMode = POINTER(DeviceSharedMode) 52 | 53 | class WAVEFORMATEX(ctypes.Structure): 54 | _fields_ = [ 55 | ('wFormatTag', WORD), 56 | ('nChannels', WORD), 57 | ('nSamplesPerSec', WORD), 58 | ('nAvgBytesPerSec', WORD), 59 | ('nBlockAlign', WORD), 60 | ('wBitsPerSample', WORD), 61 | ('cbSize', WORD), 62 | ] 63 | 64 | 65 | PWAVEFORMATEX = POINTER(WAVEFORMATEX) 66 | 67 | class _tagpropertykey(ctypes.Structure): 68 | pass 69 | 70 | 71 | class tag_inner_PROPVARIANT(ctypes.Structure): 72 | pass 73 | 74 | PROPVARIANT = tag_inner_PROPVARIANT 75 | PPROPVARIANT = POINTER(PROPVARIANT) 76 | 77 | PROPERTYKEY = _tagpropertykey 78 | PPROPERTYKEY = POINTER(_tagpropertykey) 79 | 80 | class ERole(enum): 81 | eConsole = 0 82 | eMultimedia = 1 83 | eCommunications = 2 84 | ERole_enum_count = 3 85 | 86 | 87 | class IPolicyConfig(comtypes.IUnknown): 88 | _case_insensitive_ = True 89 | _iid_ = IID_IPolicyConfig 90 | _methods_ = ( 91 | COMMETHOD( 92 | [], 93 | HRESULT, 94 | 'GetMixFormat', 95 | (['in'], LPCWSTR, 'pwstrDeviceId'), 96 | (['out'], POINTER(PWAVEFORMATEX), 'pFormat') 97 | ), 98 | COMMETHOD( 99 | [], 100 | HRESULT, 101 | 'GetDeviceFormat', 102 | (['in'], LPCWSTR, 'pwstrDeviceId'), 103 | (['in'], BOOL, 'bDefault'), 104 | (['out'], POINTER(PWAVEFORMATEX), 'pFormat') 105 | ), 106 | COMMETHOD( 107 | [], 108 | HRESULT, 109 | 'ResetDeviceFormat', 110 | (['in'], LPCWSTR, 'pwstrDeviceId') 111 | ), 112 | COMMETHOD( 113 | [], 114 | HRESULT, 115 | 'SetDeviceFormat', 116 | (['in'], LPCWSTR, 'pwstrDeviceId'), 117 | (['in'], PWAVEFORMATEX, 'pEndpointFormat'), 118 | (['in'], PWAVEFORMATEX, 'pMixFormat') 119 | ), 120 | 121 | COMMETHOD( 122 | [], 123 | HRESULT, 124 | 'GetProcessingPeriod', 125 | (['in'], LPCWSTR, 'pwstrDeviceId'), 126 | (['in'], BOOL, 'bDefault'), 127 | (['out'], LPREFERENCE_TIME, 'hnsDefaultDevicePeriod'), 128 | (['out'], LPREFERENCE_TIME, 'hnsMinimumDevicePeriod') 129 | ), 130 | COMMETHOD( 131 | [], 132 | HRESULT, 133 | 'SetProcessingPeriod', 134 | (['in'], LPCWSTR, 'pwstrDeviceId'), 135 | (['in'], LPREFERENCE_TIME, 'hnsDevicePeriod') 136 | ), 137 | COMMETHOD( 138 | [], 139 | HRESULT, 140 | 'GetShareMode', 141 | (['in'], LPCWSTR, 'pwstrDeviceId'), 142 | (['out'], PDeviceSharedMode, 'pMode') 143 | ), 144 | COMMETHOD( 145 | [], 146 | HRESULT, 147 | 'SetShareMode', 148 | (['in'], LPCWSTR, 'pwstrDeviceId'), 149 | (['in'], PDeviceSharedMode, 'pMode') 150 | ), 151 | COMMETHOD( 152 | [], 153 | HRESULT, 154 | 'GetPropertyValue', 155 | (['in'], LPCWSTR, 'pwstrDeviceId'), 156 | (['in'], PPROPERTYKEY, 'key'), 157 | (['out'], PPROPVARIANT, 'pValue') 158 | ), 159 | COMMETHOD( 160 | [], 161 | HRESULT, 162 | 'SetPropertyValue', 163 | (['in'], LPCWSTR, 'pwstrDeviceId'), 164 | (['in'], PPROPERTYKEY, 'key'), 165 | (['in'], PPROPVARIANT, 'pValue') 166 | ), 167 | COMMETHOD( 168 | [], 169 | HRESULT, 170 | 'SetDefaultEndpoint', 171 | (['in'], LPCWSTR, 'pwstrDeviceId'), 172 | (['in'], ERole, 'ERole') 173 | ), 174 | COMMETHOD( 175 | [], 176 | HRESULT, 177 | 'SetEndpointVisibility', 178 | (['in'], LPCWSTR, 'pwstrDeviceId'), 179 | (['in'], BOOL, 'bVisible') 180 | ) 181 | ) 182 | 183 | 184 | PIPolicyConfig = POINTER(IPolicyConfig) 185 | 186 | class AudioSes(object): 187 | name = u'AudioSes' 188 | _reg_typelib_ = (IID_AudioSes, 1, 0) 189 | 190 | 191 | class CPolicyConfigClient (comtypes.CoClass): 192 | _reg_clsid_ = CLSID_PolicyConfigClient 193 | _idlflags_ = [] 194 | _reg_typelib_ = (IID_AudioSes, 1, 0) 195 | _com_interfaces_ = [IPolicyConfig] -------------------------------------------------------------------------------- /new_src/utils/powerplan.py: -------------------------------------------------------------------------------- 1 | from util import runCommandLine 2 | 3 | 4 | def get_powerplans(): 5 | pplans={} 6 | current = None 7 | for powerplan in runCommandLine("powercfg -List").split("\n"): 8 | if ":" in powerplan: 9 | ParsedData = powerplan.split(":")[1].split() 10 | the_data = (ParsedData[0]) 11 | plan_name = (" ".join(ParsedData[1:])) 12 | 13 | if "*" in plan_name: 14 | plan_name = plan_name[plan_name.find("(") + 1: plan_name.find(")")] 15 | pplans[plan_name]=the_data 16 | current = plan_name 17 | else: 18 | plan_name = plan_name[plan_name.find("(") + 1: plan_name.find(")")] 19 | pplans[plan_name]=the_data 20 | return (pplans, current) 21 | 22 | def change_pplan(choice): 23 | the_thing=(get_powerplans()) 24 | runCommandLine(f"powercfg.exe /S {the_thing[choice]}") -------------------------------------------------------------------------------- /new_src/utils/rotateDisplay.py: -------------------------------------------------------------------------------- 1 | import win32api 2 | import win32con 3 | 4 | 5 | def rotate_display(display_num, rotate_choice): 6 | display_num = display_num.split(":")[0] 7 | display_num = display_num -1 8 | rotation_val="" 9 | if (rotate_choice != None): 10 | if (rotate_choice == "180"): 11 | rotation_val=win32con.DMDO_180 12 | elif(rotate_choice == "90"): 13 | rotation_val=win32con.DMDO_270 14 | elif (rotate_choice == "270"): 15 | rotation_val=win32con.DMDO_90 16 | else: 17 | rotation_val=win32con.DMDO_DEFAULT 18 | 19 | device = win32api.EnumDisplayDevices(None,display_num) 20 | dm = win32api.EnumDisplaySettings(device.DeviceName,win32con.ENUM_CURRENT_SETTINGS) 21 | if((dm.DisplayOrientation + rotation_val)%2==1): 22 | dm.PelsWidth, dm.PelsHeight = dm.PelsHeight, dm.PelsWidth 23 | dm.DisplayOrientation = rotation_val 24 | 25 | win32api.ChangeDisplaySettingsEx(device.DeviceName,dm) -------------------------------------------------------------------------------- /new_src/utils/util.py: -------------------------------------------------------------------------------- 1 | import os 2 | import subprocess 3 | from ctypes import windll 4 | import win32gui 5 | import pyautogui 6 | 7 | def windowsSettings(choice=False): 8 | 9 | settings ={ 10 | "SYSTEM: Display": 'ms-settings:display', 11 | "SYSTEM: Advanced Display": 'ms-settings:display-advanced', 12 | "SYSTEM: Night Light": 'ms-settings:nightlight', 13 | "SYSTEM: Sound": 'ms-settings:sound', 14 | "SYSTEM: Manage Sound Devices": 'ms-settings:sound-devices', 15 | "SYSTEM: Manage App/Device Volume": 'ms-settings:apps-volume', 16 | "SYSTEM: App Volume & Device Preferences": 'ms-settings:apps-volume', 17 | "SYSTEM: Notifcations & Actions": 'ms-settings:notifications', 18 | "SYSTEM: Power & Sleep": 'ms-settings:powersleep', 19 | "SYSTEM: Battery": 'ms-settings:batterysaver', 20 | "SYSTEM: Battery Usage Details": 'ms-settings:batterysaver-usagedetails', 21 | "SYSTEM: Default Save Locations": 'ms-settings:savelocations', 22 | "SYSTEM: Multi-Tasking": 'ms-settings:multitasking', 23 | "SYSTEM: Sign-in Options": 'ms-settings:signinoptions', ## this was 'ACCOUNTS' 24 | "SYSTEM: Date & Time": 'ms-settings:dateandtime', ## this was 'TIME & LANGUAGE* 25 | "SYSTEM: Time Region": 'ms-settings:regionformatting', ## this was 'TIME & LANGUAGE* 26 | "SYSTEM: Settings Home Page": 'ms-settings:', 27 | "NETWORK: Ethernet": 'ms-settings:network-ethernet', 28 | "NETWORK: Wi-Fi": 'ms-settings:network-wifi', 29 | "PERSONALIZATION: Background": 'ms-settings:personalization-background', 30 | "PERSONALIZATION: Colors": 'ms-settings:personalization-colors', 31 | "PERSONALIZATION: Lock Screen": 'ms-settings:lockscreen', 32 | "PERSONALIZATION: Themes": 'ms-settings:themes', 33 | "PERSONALIZATION: Start Folders": 'ms-settings:personalization-start-places', 34 | "APPS: Apps & Features": 'ms-settings:appsfeatures', 35 | "APPS: Manage Startup Apps": 'ms-settings:startupapps', 36 | "APPS: Manage Default Apps": 'ms-settings:defaultapps', 37 | "APPS: Manage Optional Features": 'ms-settings:optionalfeatures', 38 | "GAMING: Game Bar": 'ms-settings:gaming-gamebar', 39 | "GAMING: Game DVR": 'ms-settings:gaming-gamedvr', 40 | "GAMING: Game Mode": 'ms-settings:gaming-gamemode', 41 | "GAMING: XBOX Networking": 'ms-settings:gaming-xboxnetworking', 42 | "PRIVACY: Activity History": 'ms-settings:privacy-activityhistory', 43 | "PRIVACY: Webcam": 'ms-settings:privacy-webcam', 44 | "PRIVACY: Microphone": 'ms-settings:privacy-microphone', 45 | "PRIVACY: Background Apps": 'ms-settings:privacy-backgroundapps', 46 | r"UPDATE & SECURITY: Windows Update": 'ms-settings:windowsupdate', 47 | r"UPDATE & SECURITY: Windows Recovery": 'ms-settings:recovery', 48 | r"UPDATE & SECURITY: Update history": 'ms-settings:windowsupdate-history', 49 | r"UPDATE & SECURITY: Restart Options": 'ms-settings:windowsupdate-restartoptions', 50 | r"UPDATE & SECURITY: Delivery Optimization": 'ms-settings:delivery-optimization', 51 | r"UPDATE & SECURITY: Windows Security": 'ms-settings:windowsdefender', 52 | r"UPDATE & SECURITY: Windows Defender": 'windowsdefender:', 53 | r"UPDATE & SECURITY: For Developers": 'ms-settings:developers', 54 | } 55 | if not choice: 56 | return list(settings.keys()) 57 | else: 58 | os.system(f'explorer "{settings[choice]}"') 59 | 60 | def runCommandLine(command): 61 | systemencoding = windll.kernel32.GetConsoleOutputCP() 62 | systemencoding= f"cp{systemencoding}" 63 | output = subprocess.run(command, stdout=subprocess.PIPE, shell=True) 64 | result = str(output.stdout.decode(systemencoding)) 65 | return result 66 | 67 | def get_windows(): 68 | results = [] 69 | def winEnumHandler(hwnd, ctx): 70 | if win32gui.IsWindowVisible(hwnd): 71 | if win32gui.GetWindowText(hwnd): 72 | 73 | results.append(win32gui.GetWindowText(hwnd)) 74 | 75 | win32gui.EnumWindows(winEnumHandler, None) 76 | return results 77 | 78 | def AdvancedMouseFunction(x, y, delay, look): 79 | if look == 0: 80 | look = None 81 | if look == "None": 82 | try: 83 | pyautogui.moveTo(x, y, delay) 84 | except: 85 | pass 86 | elif look == "Start slow, end fast": 87 | try: 88 | pyautogui.moveTo(x, y, delay, pyautogui.easeInQuad) 89 | except: 90 | pass 91 | elif look == "Start fast, end slow": 92 | try: 93 | pyautogui.moveTo(x, y, delay, pyautogui.easeOutQuad) 94 | except: 95 | pass 96 | elif look == "Start and end fast, slow in middle": 97 | try: 98 | pyautogui.moveTo(x, y, delay, pyautogui.easeInOutQuad) 99 | except: 100 | pass 101 | elif look == "bounce at the end": 102 | try: 103 | pyautogui.moveTo(x, y, delay, pyautogui.easeInBounce) 104 | except: 105 | pass 106 | elif look == "rubber band at the end": 107 | try: 108 | pyautogui.moveTo(x, y, delay, pyautogui.easeInElastic) 109 | except: 110 | pass 111 | 112 | import json 113 | 114 | def AudioDeviceCmdlets(command, output=True): 115 | ### add in another coinitilize??? 116 | 117 | systemencoding = windll.kernel32.GetConsoleOutputCP() 118 | systemencoding= f"cp{systemencoding}" 119 | process = subprocess.Popen(["powershell", "-Command", "Import-Module .\AudioDeviceCmdlets.dll;", command],stdout=subprocess.PIPE, shell=True, encoding=systemencoding) 120 | proc_stdout = process.communicate()[0] 121 | if output: 122 | proc_stdout = proc_stdout[proc_stdout.index("["):-1] 123 | print(proc_stdout) 124 | return json.loads(proc_stdout) 125 | 126 | 127 | import pyttsx3 128 | import sounddevice as sd 129 | 130 | 131 | def getAllVoices(): 132 | engine = pyttsx3.init() 133 | return engine.getProperty("voices") 134 | 135 | def getAllOutput_TTS2(): 136 | audio_dict = {} 137 | for outputDevice in sd.query_hostapis(0)['devices']: 138 | if sd.query_devices(outputDevice)['max_output_channels'] > 0: 139 | audio_dict[sd.query_devices(device=outputDevice)['name']] = sd.query_devices(device=outputDevice)['default_samplerate'] 140 | return audio_dict 141 | 142 | 143 | import ctypes 144 | 145 | import numpy as np 146 | import pyautogui 147 | import win32gui 148 | from PIL import Image 149 | 150 | 151 | def get_windows(): 152 | results = [] 153 | def winEnumHandler(hwnd, ctx): 154 | if win32gui.IsWindowVisible(hwnd): 155 | if win32gui.GetWindowText(hwnd): 156 | 157 | results.append(win32gui.GetWindowText(hwnd)) 158 | 159 | win32gui.EnumWindows(winEnumHandler, None) 160 | return results 161 | 162 | def winextra(action): 163 | 164 | # if action == "Keep Active, Minimize All (Toggle)": 165 | # pyautogui.hotkey('win', 'home') 166 | # 167 | # if action == "Minimize All (Toggle)": 168 | # pyautogui.hotkey('win', 'd') 169 | # 170 | # if action =="Clipboard History": 171 | # pyautogui.hotkey('win', 'v') 172 | 173 | if action == "Emoji": 174 | pyautogui.hotkey('win', '.') 175 | 176 | if action == "Keyboard": 177 | pyautogui.hotkey('win', 'ctrl', "o") 178 | 179 | def get_key_state(key): 180 | hllDll = ctypes.WinDLL ("User32.dll") 181 | if key == "NUM LOCK": 182 | return hllDll.GetKeyState(0x90) 183 | if key == "CAPS LOCK": 184 | return hllDll.GetKeyState(0x14) 185 | 186 | def move_win_button(direction): 187 | check = get_key_state('NUM LOCK') 188 | if not check: 189 | pyautogui.hotkey('win', 'shift', direction) 190 | elif check: 191 | pyautogui.press('numlock') 192 | pyautogui.hotkey('win', 'shift', direction) 193 | pyautogui.press('numlock') 194 | 195 | def resize_image(im, height, width): 196 | if im.size[0] == height and im.size[1] == width: 197 | return im 198 | else: 199 | print("We are actually resizing") 200 | size = (height,width) 201 | im.load() 202 | bands = list(im.split()) 203 | a = np.asarray(bands[-1]) 204 | a.flags.writeable = True 205 | a[a != 0] = 1 206 | bands[-1] = Image.fromarray(a) 207 | bands = [b.resize(size, Image.LINEAR) for b in bands] 208 | a = np.asarray(bands[-1]) 209 | a.flags.writeable = True 210 | a[a != 0] = 255 211 | bands[-1] = Image.fromarray(a) 212 | im = Image.merge('RGBA', bands) 213 | return im -------------------------------------------------------------------------------- /new_src/utils/virtualDesktop.py: -------------------------------------------------------------------------------- 1 | from pyvda import AppView, VirtualDesktop, get_virtual_desktops 2 | from WinTool import TPClient 3 | 4 | 5 | def current_vd(): 6 | current_d = VirtualDesktop.current() 7 | TPClient.stateUpdate(f"KillerBOSS.TP.Plugins.virtualdesktop.current_vd", f"[{current_d.number}] {current_d.name}") 8 | return current_d 9 | 10 | def vd_pinn_app(pinned=True): 11 | if pinned: 12 | AppView.current() 13 | AppView.current().pin() 14 | if not pinned: 15 | current_window = AppView.current() 16 | target_desktop = VirtualDesktop(current_vd().number) 17 | current_window.move(target_desktop) 18 | 19 | 20 | 21 | def virtual_desktop(target_desktop=None, move=False, pinned=False): 22 | number_of_active_desktops = len(get_virtual_desktops()) 23 | """Retrieving VD Number from name""" 24 | target_desktop = int(target_desktop[target_desktop.find("[") + 1: target_desktop.find("]")]) 25 | 26 | if target_desktop == "Next": 27 | if move: 28 | current_window = AppView.current() 29 | target_desktop = VirtualDesktop(target_desktop) 30 | current_window.move(target_desktop) 31 | if pinned: 32 | AppView.current().pin() 33 | elif not move: 34 | if target_desktop <= number_of_active_desktops: 35 | VirtualDesktop(target_desktop).go() 36 | else: 37 | print("too many") 38 | 39 | elif target_desktop == "Previous": 40 | if move: 41 | AppView.current().move(VirtualDesktop(target_desktop)) 42 | if pinned: 43 | AppView.current().pin() 44 | 45 | elif not move: 46 | if target_desktop > 0: 47 | if pinned: 48 | AppView.current().pin() 49 | VirtualDesktop(target_desktop).go() 50 | else: 51 | pass 52 | 53 | elif target_desktop != "Previous" or "Next": 54 | if move: 55 | if pinned: 56 | AppView.current().move(VirtualDesktop(target_desktop)) 57 | vd_pinn_app() 58 | VirtualDesktop(target_desktop).go() 59 | else: 60 | AppView.current().move(VirtualDesktop(target_desktop)) 61 | elif not move: 62 | if target_desktop > 0: 63 | VirtualDesktop(target_desktop).go() 64 | if pinned: 65 | vd_pinn_app() 66 | current_vd() 67 | 68 | def rename_vd(name, number=None): 69 | number_of_active_desktops = len(get_virtual_desktops()) 70 | new_vd = VirtualDesktop(number_of_active_desktops) 71 | VirtualDesktop.rename(new_vd, name) 72 | 73 | 74 | def create_vd(name=None): 75 | if name: 76 | VirtualDesktop.create() 77 | rename_vd(name) 78 | else: 79 | VirtualDesktop.create() 80 | 81 | 82 | 83 | def remove_vd(remove, fallbacknum=None): 84 | if fallbacknum: 85 | try: 86 | fall_back =VirtualDesktop(fallbacknum) 87 | remove_vd = VirtualDesktop(remove) 88 | VirtualDesktop.remove(remove_vd, fall_back) 89 | except ValueError as err: 90 | return err 91 | else: 92 | try: 93 | remove_vd=VirtualDesktop(remove) 94 | VirtualDesktop.remove(remove_vd) 95 | except ValueError as err: 96 | return err 97 | current_vd() 98 | 99 | 100 | 101 | def get_vd_name(number): 102 | name = VirtualDesktop(number).name 103 | if not name: 104 | name = f"Desktop {number}" 105 | return name 106 | 107 | old_vd = [] 108 | def vd_check(): 109 | global old_vd 110 | vdlist=[] 111 | vdlist.append("Next") 112 | vdlist.append("Previous") 113 | virtual_desks = get_virtual_desktops() 114 | for item in virtual_desks: 115 | if not item.name: 116 | vdlist.append(f"[{item.number}] Desktop {item.number}") 117 | else: 118 | vdlist.append(f"[{item.number}] {item.name}") 119 | if vdlist != old_vd: 120 | TPClient.choiceUpdate("KillerBOSS.TP.Plugins.virtualdesktop.actionchoice", vdlist) 121 | old_vd = vdlist -------------------------------------------------------------------------------- /new_src/utils/winNotification.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from winotify import PY_EXE, Notifier, Registry, audio 4 | 5 | app_id = "WinTools-Notify" 6 | app_path = os.path.abspath(__file__) 7 | r = Registry(app_id, PY_EXE, app_path, force_override=True) 8 | notifier = Notifier(r) 9 | 10 | @notifier.register_callback 11 | def clear_notify(): 12 | notifier.clear() 13 | 14 | 15 | def win_toast(atitle="", amsg="", buttonText = "", buttonlink = "", sound = "", aduration="short", icon=""): 16 | ### setting the base notification stuff 17 | if not os.path.exists(rf"{icon}") or icon == "": icon = os.path.join(os.getcwd(),"src\icon.png") 18 | 19 | toast = notifier.create_notification( 20 | title=atitle, 21 | msg=amsg, 22 | icon=icon, 23 | duration = aduration.lower(), 24 | ) 25 | 26 | ### we can allow multiple links 27 | if buttonText != "" and buttonlink != "": 28 | toast.add_actions(label=buttonText, 29 | launch=buttonlink) 30 | # toast.add_actions("Open Github", "https://github.com/versa-syahptr/winotify") 31 | # toast.add_actions("Quit app", "Kewl") 32 | # toast.add_actions("spam", "sweet") 33 | 34 | audioDic = { 35 | "Default": audio.Default, 36 | "IM": audio.IM, 37 | "Mail": audio.Mail, 38 | "Reminder": audio.Mail, 39 | "SMS": audio.SMS, 40 | "LoopingAlarm1": audio.LoopingAlarm, 41 | "LoopingAlarm2": audio.LoopingAlarm2, 42 | "LoopingAlarm3": audio.LoopingAlarm3, 43 | "LoopingAlarm4": audio.LoopingAlarm4, 44 | "LoopingAlarm5": audio.LoopingAlarm6, 45 | "LoopingAlarm6": audio.LoopingAlarm8, 46 | "LoopingAlarm7": audio.LoopingAlarm9, 47 | "LoopingAlarm8": audio.LoopingAlarm10, 48 | "LoopingCall1": audio.LoopingCall, 49 | "LoopingCall2": audio.LoopingCall, 50 | "LoopingCall3": audio.LoopingCall, 51 | "LoopingCall4": audio.LoopingCall, 52 | "LoopingCall5": audio.LoopingCall, 53 | "LoopingCall6": audio.LoopingCall, 54 | "LoopingCall7": audio.LoopingCall, 55 | "LoopingCall8": audio.LoopingCall, 56 | "LoopingCall9": audio.LoopingCall, 57 | "LoopingCall10": audio.LoopingCall, 58 | "Silent": audio.Silent, 59 | } 60 | 61 | toast.set_audio(audioDic[sound], loop=False) 62 | 63 | toast.build() 64 | toast.show() -------------------------------------------------------------------------------- /new_src/utils/winShutdown.py: -------------------------------------------------------------------------------- 1 | import pyautogui 2 | import os 3 | 4 | def win_shutdown(time, cancel=False): 5 | ## should we create a shutdown timer/countdown ?? we can warn the user 5 minutes before shutting down so they can cancel 6 | 7 | ## IF Blank then we show the GUI 8 | if time == "": 9 | time_set= pyautogui.prompt(text='💻 How many MINUTES do you want to wait before shutting down?', title='Shutdown PC?', default='') 10 | if time_set == "0": 11 | os.system(f"shutdown -a") 12 | pyautogui.alert("❗ ABORTED SYSTEM SHUTDOWN ❗") 13 | time="DONE" 14 | if type(time) == int: 15 | if int(time_set) > 0: 16 | print(f"Shutdown in {time_set} minutes") 17 | time_set = int(time_set) * 60 18 | os.system(f"shutdown -s -t {time}") 19 | time="DONE" 20 | 21 | if time == "NOW": 22 | os.system(f"shutdown -s -t 0") 23 | 24 | if type(time) == int: 25 | 26 | if int(time) >0: 27 | try: 28 | print("Shutdown soon?") 29 | time = int(time) * 60 30 | os.system(f"shutdown -s -t {time}") 31 | except: 32 | pass 33 | elif int(time) == None or 0: 34 | os.system(f"shutdown -a") 35 | pyautogui.alert("❗ ABORTED SYSTEM SHUTDOWN ❗") -------------------------------------------------------------------------------- /patchnotes.txt: -------------------------------------------------------------------------------- 1 | - Fixed issue with Notebook PC's actions not filling out 2 | - Re-added in Action to Check if a process is running 3 | and open if not or focus it. 4 | -------------------------------------------------------------------------------- /src/AudioDeviceCmdlets.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KillerBOSS2019/WinTools/d5cbbe721b5ff150e7b3a4afe9dca41a82c31ca5/src/AudioDeviceCmdlets.dll -------------------------------------------------------------------------------- /src/compile.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import shutil 4 | 5 | with open("entry.tp") as entry: 6 | entry = json.loads(entry.read()) 7 | 8 | startcmd = entry['plugin_start_cmd'].split("%TP_PLUGIN_FOLDER%")[1].split("\\") 9 | filedirectory = startcmd[0] 10 | fileName = startcmd[1] 11 | 12 | if os.path.exists(filedirectory): 13 | os.remove(os.path.join(os.getcwd(), "WinTools")) 14 | else: 15 | os.makedirs("temp/"+filedirectory) 16 | 17 | 18 | for file in os.listdir("."): 19 | if file not in ["compile.py", "utils", "requirements.txt", "build", "dist", "main.py", "main.spec", "__pycache__", "temp"]: 20 | print("copying", file) 21 | shutil.copy(os.path.join(os.getcwd(), file), os.path.join("temp", filedirectory)) 22 | 23 | os.rename("dist\Main.exe", "dist\WinTools.exe") 24 | shutil.copy(os.path.join(os.getcwd(), r"dist\WinTools.exe"), "temp/"+filedirectory) 25 | 26 | shutil.make_archive(base_name="WinTools", format='zip', root_dir="temp", base_dir="WinTools") 27 | os.rename("WinTools.zip", "WinTools.tpp") 28 | -------------------------------------------------------------------------------- /src/entry.tp: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": 4, 3 | "version": 231, 4 | "name": "Windows-Tools", 5 | "id": "Windows-Tools", 6 | "configuration": { 7 | "colorDark": "#6c6f73", 8 | "colorLight": "#3d62ad" 9 | }, 10 | "plugin_start_cmd": "%TP_PLUGIN_FOLDER%WinTools\\WinTools.exe", 11 | "categories": [ 12 | 13 | { 14 | "id":"Public IP", 15 | "name":"Public IP Info", 16 | "events":[ 17 | ], 18 | "states":[ 19 | { 20 | "id":"KillerBOSS.TP.Plugins.publicip.ip", 21 | "type":"text", 22 | "desc":"Public IP: IP Address", 23 | "default":"" 24 | }, 25 | { 26 | "id":"KillerBOSS.TP.Plugins.publicip.city", 27 | "type":"text", 28 | "desc":"Pubic IP: City", 29 | "default":"" 30 | }, 31 | { 32 | "id":"KillerBOSS.TP.Plugins.publicip.country", 33 | "type":"text", 34 | "desc":"Public IP: Country", 35 | "default":"" 36 | }, 37 | { 38 | "id":"KillerBOSS.TP.Plugins.publicip.region", 39 | "type":"text", 40 | "desc":"Public IP: Region", 41 | "default":"" 42 | }, 43 | { 44 | "id":"KillerBOSS.TP.Plugins.publicip.timezone", 45 | "type":"text", 46 | "desc":"Pubic IP: Timezone", 47 | "default":"" 48 | }, 49 | { 50 | "id":"KillerBOSS.TP.Plugins.publicip.organization", 51 | "type":"text", 52 | "desc":"Pubic IP: Internet Provider", 53 | "default":"" 54 | } 55 | ] 56 | }, 57 | 58 | { 59 | "id": "main", 60 | "name": "Windows-Tool", 61 | "imagepath": "%TP_PLUGIN_FOLDER%WinTools\\icon.png", 62 | "connectors": [ 63 | { 64 | "id": "KillerBOSS.TP.Plugins.VolumeMixer.connectors.APPcontrol", 65 | "name": "APP Volume slider", 66 | "format": "Control volume for {$KillerBOSS.TP.Plugins.VolumeMixer.slidercontrol$}", 67 | "data": [ 68 | { 69 | "id": "KillerBOSS.TP.Plugins.VolumeMixer.slidercontrol", 70 | "type": "choice", 71 | "label": "choice", 72 | "default": "", 73 | "valueChoices": [] 74 | } 75 | ] 76 | }, 77 | { 78 | "id": "KillerBOSS.TP.Plugins.Magnifier.connectors.ZoomControl", 79 | "name": "Magnify Zoom Slider", 80 | "format": "Adjust Magnifier: {$KillerBOSS.TP.Plugins.Magnifier.ZoomControl$}", 81 | "data": [ 82 | { 83 | "id": "KillerBOSS.TP.Plugins.Magnifier.ZoomControl", 84 | "description": "Manually adjust Lens Size and Zoom", 85 | "type": "choice", 86 | "label": "choice", 87 | "default": "", 88 | "valueChoices": ["Zoom", "Lens X", "Lens Y"] 89 | } 90 | ] 91 | } 92 | 93 | ], 94 | "actions": [ 95 | { 96 | "id": "KillerBOSS.TP.Plugins.VolumeMixer.Mute/Unmute", 97 | "name": "Volume Mixer: Mute/Unmute process volume", 98 | "prefix": "plugin", 99 | "type": "communicate", 100 | "tryInline": true, 101 | "format": "{$KillerBOSS.TP.Plugins.VolumeMixer.Mute/Unmute.Choice$} Program:{$KillerBOSS.TP.Plugins.VolumeMixer.Mute/Unmute.process$}", 102 | "data": [ 103 | { 104 | "id": "KillerBOSS.TP.Plugins.VolumeMixer.Mute/Unmute.process", 105 | "type": "choice", 106 | "label": "choice", 107 | "default": "", 108 | "valueChoices": [] 109 | }, 110 | { 111 | "id": "KillerBOSS.TP.Plugins.VolumeMixer.Mute/Unmute.Choice", 112 | "type": "choice", 113 | "label": "choice", 114 | "default": "Mute", 115 | "valueChoices": [ 116 | "Mute", 117 | "Unmute" 118 | ] 119 | } 120 | ] 121 | }, 122 | { 123 | "id": "KillerBOSS.TP.Plugins.VolumeMixer.Increase/DecreaseVolume", 124 | "name": "Volume Mixer: Increase/Decrease process volume", 125 | "prefix": "plugin", 126 | "type": "communicate", 127 | "tryInline": true, 128 | "format": "{$KillerBOSS.TP.Plugins.VolumeMixer.Increase/DecreaseVolume.Ince/DecreChoice$}{$KillerBOSS.TP.Plugins.VolumeMixer.Increase/DecreaseVolume.process$}Volume to {$KillerBOSS.TP.Plugins.VolumeMixer.Increase/DecreaseVolume.Volume$}", 129 | "hasHoldFunctionality": true, 130 | "data": [ 131 | { 132 | "id": "KillerBOSS.TP.Plugins.VolumeMixer.Increase/DecreaseVolume.process", 133 | "type": "choice", 134 | "label": "choice", 135 | "default": "", 136 | "valueChoices": [] 137 | }, 138 | { 139 | "id": "KillerBOSS.TP.Plugins.VolumeMixer.Increase/DecreaseVolume.Ince/DecreChoice", 140 | "type": "choice", 141 | "label": "choice", 142 | "default": "Increase", 143 | "valueChoices": [ 144 | "Increase", 145 | "Decrease", 146 | "Set" 147 | ] 148 | }, 149 | { 150 | "id": "KillerBOSS.TP.Plugins.VolumeMixer.Increase/DecreaseVolume.Volume", 151 | "type": "number", 152 | "label": "choice", 153 | "allowDecimals": false, 154 | "minValue": 0, 155 | "maxValue": 100, 156 | "default": 10 157 | } 158 | ] 159 | }, 160 | { 161 | "id": "KillerBOSS.TP.Plugins.ChangeAudioOutput", 162 | "name": "Sound: Change Input/Output Device", 163 | "prefix": "plugin", 164 | "type": "communicate", 165 | "tryInline": true, 166 | "format": "Change Audio{$KillerBOSS.TP.Plugins.ChangeAudioOutput.Choice$} to Device{$KillerBOSS.TP.Plugins.ChangeAudioOutput.Device$}", 167 | "data": [ 168 | { 169 | "id": "KillerBOSS.TP.Plugins.ChangeAudioOutput.Choice", 170 | "type": "choice", 171 | "label": "choice", 172 | "default": "Pick One", 173 | "valueChoices": [ 174 | "Output", 175 | "Input" 176 | ] 177 | }, 178 | { 179 | "id": "KillerBOSS.TP.Plugins.ChangeAudioOutput.Device", 180 | "type": "choice", 181 | "label": "choice", 182 | "default": "", 183 | "valueChoices": [] 184 | } 185 | ] 186 | }, 187 | { 188 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.HoldDownToggle", 189 | "name": "Mouse: Toggle Mouse Down/Up", 190 | "prefix": "plugin", 191 | "type": "communicate", 192 | "tryInline": true, 193 | "format": "Mouse: Set Mouse Statement to Mouse{$KillerBOSS.TP.Plugins.AdvanceMouse.HoldDownToggle.Toggle$} on {$KillerBOSS.TP.Plugins.AdvanceMouse.HoldDownToggle.ButtonPick$}Button", 194 | "data": [ 195 | { 196 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.HoldDownToggle.Toggle", 197 | "type": "choice", 198 | "label": "choice", 199 | "default": "Down", 200 | "valueChoices": [ 201 | "Down", 202 | "Up" 203 | ] 204 | }, 205 | { 206 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.HoldDownToggle.ButtonPick", 207 | "type": "choice", 208 | "label": "choice", 209 | "default": "Left", 210 | "valueChoices": [ 211 | "Left", 212 | "Right" 213 | ] 214 | } 215 | ] 216 | }, 217 | { 218 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.StopMouseUpdate", 219 | "name": "Mouse: Stop X, Y Update (Togglable)", 220 | "prefix": "plugin", 221 | "type": "communicate", 222 | "tryInline": true, 223 | "hasHoldFunctionality": false, 224 | "format": "Turn {$KillerBOSS.TP.Plugins.AdvanceMouse.StopMouseUpdate.TogglePick$} Update X, Y", 225 | "data": [ 226 | { 227 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.StopMouseUpdate.TogglePick", 228 | "type": "choice", 229 | "label": "choice", 230 | "default": "OFF", 231 | "valueChoices": [ 232 | "OFF", 233 | "ON" 234 | ] 235 | } 236 | ] 237 | }, 238 | { 239 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.Function", 240 | "name": "Mouse: Move Mouse X, Y", 241 | "prefix": "plugin", 242 | "type": "communicate", 243 | "tryInline": true, 244 | "hasHoldFunctionality": true, 245 | "format": "Increase Mouse X:{$KillerBOSS.TP.Plugins.AdvanceMouse.Function.X$} Y:{$KillerBOSS.TP.Plugins.AdvanceMouse.Function.Y$}", 246 | "data": [ 247 | { 248 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.Function.X", 249 | "type": "number", 250 | "label": "number", 251 | "default": 10, 252 | "allowDecimals": false 253 | }, 254 | { 255 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.Function.Y", 256 | "type": "number", 257 | "label": "number", 258 | "default": 10, 259 | "allowDecimals": false 260 | } 261 | ] 262 | }, 263 | { 264 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.teleport", 265 | "name": "Mouse: Teleport Mouse X, Y with delay, animation", 266 | "prefix": "plugin", 267 | "type": "communicate", 268 | "tryInline": true, 269 | "format": "Mouse: Teleport Mouse to X:{$KillerBOSS.TP.Plugins.AdvanceMouse.teleport.X$} Y:{$KillerBOSS.TP.Plugins.AdvanceMouse.teleport.Y$} with animation Type:{$KillerBOSS.TP.Plugins.AdvanceMouse.teleport.animation$} with speed:{$KillerBOSS.TP.Plugins.AdvanceMouse.teleport.Speed$}", 270 | "data": [ 271 | { 272 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.teleport.X", 273 | "type": "number", 274 | "label": "number", 275 | "default": 10, 276 | "allowDecimals": false 277 | }, 278 | { 279 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.teleport.Y", 280 | "type": "number", 281 | "label": "number", 282 | "default": 10, 283 | "allowDecimals": false 284 | }, 285 | { 286 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.teleport.animation", 287 | "type": "choice", 288 | "label": "choice", 289 | "default": "None", 290 | "valueChoices": [ 291 | "Start slow, end fast", 292 | "Start fast, end slow", 293 | "Start and end fast, slow in middle", 294 | "bounce at the end", 295 | "rubber band at the end", 296 | "None" 297 | ] 298 | }, 299 | { 300 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.teleport.Speed", 301 | "type": "number", 302 | "label": "number", 303 | "default": 10, 304 | "allowDecimals": false 305 | } 306 | ] 307 | }, 308 | { 309 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.MouseClick", 310 | "name": "Mouse: Advanced Mouse Click", 311 | "prefix": "plugin", 312 | "type": "communicate", 313 | "tryInline": true, 314 | "hasHoldFunctionality": true, 315 | "format": "Mouse: Click {$KillerBOSS.TP.Plugins.AdvanceMouse.MouseClick.Times$}Times with delay in between{$KillerBOSS.TP.Plugins.AdvanceMouse.MouseClick.delay$}Seconds with Mouse Key:{$KillerBOSS.TP.Plugins.AdvanceMouse.MouseClick.ButtonPick$}", 316 | "data": [ 317 | { 318 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.MouseClick.Times", 319 | "type": "number", 320 | "label": "number", 321 | "default": 1, 322 | "maxValue": 50, 323 | "minValue": 1, 324 | "allowDecimals": false 325 | }, 326 | { 327 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.MouseClick.delay", 328 | "type": "number", 329 | "label": "number", 330 | "default": 0, 331 | "maxValue": 60, 332 | "minValue": 0, 333 | "allowDecimals": true 334 | }, 335 | { 336 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.MouseClick.ButtonPick", 337 | "type": "choice", 338 | "label": "choice", 339 | "default": "Left", 340 | "valueChoices": [ 341 | "Left", 342 | "Right" 343 | ] 344 | } 345 | ] 346 | }, 347 | { 348 | "id": "KillerBOSS.TP.Plugins.winsettings.active.mouseCapture", 349 | "name": "Mouse: Capture Mouse To Live Icon", 350 | "prefix": "plugin", 351 | "type": "communicate", 352 | "tryInline": true, 353 | "hasHoldFunctionality": true, 354 | "description": "Capture an area around your mouse and project to an icon.", 355 | "format": "Switch Live Mouse Capture :{$KillerBOSS.TP.Plugins.winsettings.active.mouseCapture.Switch$} -> X:{$KillerBOSS.TP.Plugins.winsettings.active.mouseCapture.xSize$} Y:{$KillerBOSS.TP.Plugins.winsettings.active.mouseCapture.ySize$} - Overlay: {$KillerBOSS.TP.Plugins.winsettings.active.mouseCapture.overlay_file$}", 356 | "data": [ 357 | { 358 | "id": "KillerBOSS.TP.Plugins.winsettings.active.mouseCapture.Switch", 359 | "type": "choice", 360 | "label": "choice", 361 | "default": "OFF", 362 | "valueChoices": ["ON", "OFF"] 363 | }, 364 | { 365 | "id": "KillerBOSS.TP.Plugins.winsettings.active.mouseCapture.xSize", 366 | "type": "number", 367 | "label": "number", 368 | "allowDecimals": false, 369 | "default": "300" 370 | }, 371 | { 372 | "id": "KillerBOSS.TP.Plugins.winsettings.active.mouseCapture.ySize", 373 | "type": "number", 374 | "label": "number", 375 | "allowDecimals": false, 376 | "default": "300" 377 | }, 378 | { 379 | "id": "KillerBOSS.TP.Plugins.winsettings.active.mouseCapture.overlay_file", 380 | "type": "choice", 381 | "label": "cursor choices", 382 | "default": "", 383 | "valueChoices": ["None", "LOAD MORE"] 384 | } 385 | ] 386 | }, 387 | { 388 | "id": "KillerBOSS.TP.Plugins.screencapture.full.file", 389 | "name": "CAPTURE: Display to File / Clipboard", 390 | "prefix": "plugin", 391 | "type": "communicate", 392 | "tryInline": true, 393 | "description": "Capture Display to Clipboard OR File", 394 | "format": "Display #{$KillerBOSS.TP.Plugins.screencapture.monitors$} to {$KillerBOSS.TP.Plugins.screencapture.window_active_capture$} and {$KillerBOSS.TP.Plugins.screencapture.filepath$} and {$KillerBOSS.TP.Plugins.screencapture.filename$}", 395 | "data": [ 396 | { 397 | "id": "KillerBOSS.TP.Plugins.screencapture.monitors", 398 | "type": "choice", 399 | "label": "choice", 400 | "default": "", 401 | "valueChoices": [] 402 | }, 403 | { 404 | "id": "KillerBOSS.TP.Plugins.screencapture.window_active_capture", 405 | "type": "choice", 406 | "label": "choice", 407 | "default": "Pick One", 408 | "valueChoices": [ 409 | "Clipboard", 410 | "File" 411 | ] 412 | }, 413 | { 414 | "id": "KillerBOSS.TP.Plugins.screencapture.filepath", 415 | "type": "folder", 416 | "label": "folder" 417 | }, 418 | { 419 | "id": "KillerBOSS.TP.Plugins.screencapture.filename", 420 | "type": "text", 421 | "label": "text", 422 | "default": "" 423 | } 424 | ] 425 | }, 426 | { 427 | "id": "KillerBOSS.TP.Plugins.screencapture.window.file", 428 | "name": "CAPTURE: Window to File / Clipboard", 429 | "prefix": "plugin", 430 | "type": "communicate", 431 | "tryInline": true, 432 | "description": "Capture Window to Clipboard OR File", 433 | "format": "Window:{$KillerBOSS.TP.Plugins.screencapture.window_name$} Save:{$KillerBOSS.TP.Plugins.screencapture.window_active_capture$} Directory->{$KillerBOSS.TP.Plugins.screencapture.filepath$} and file name ->{$KillerBOSS.TP.Plugins.screencapture.filename$} ", 434 | "data": [ 435 | { 436 | "id": "KillerBOSS.TP.Plugins.screencapture.window_name", 437 | "type": "choice", 438 | "label": "choice", 439 | "default": "", 440 | "valueChoices": [] 441 | }, 442 | { 443 | "id": "KillerBOSS.TP.Plugins.screencapture.window_capture_type", 444 | "type": "choice", 445 | "label": "choice", 446 | "default": "3", 447 | "valueChoices": [ 448 | "0", 449 | "1", 450 | "2", 451 | "3" 452 | ] 453 | }, 454 | { 455 | "id": "KillerBOSS.TP.Plugins.screencapture.filepath", 456 | "type": "folder", 457 | "label": "folder", 458 | "default": "" 459 | }, 460 | { 461 | "id": "KillerBOSS.TP.Plugins.screencapture.filename", 462 | "type": "text", 463 | "label": "text", 464 | "default": "" 465 | }, 466 | { 467 | "id": "KillerBOSS.TP.Plugins.screencapture.window_active_capture", 468 | "type": "choice", 469 | "label": "choice", 470 | "default": "Pick One", 471 | "valueChoices": [ 472 | "Clipboard", 473 | "File" 474 | ] 475 | } 476 | ] 477 | }, 478 | { 479 | "id": "KillerBOSS.TP.Plugins.screencapture.window.file.wildcard", 480 | "name": "CAPTURE: Window to File / Clipboard (*)", 481 | "prefix": "plugin", 482 | "type": "communicate", 483 | "tryInline": true, 484 | "description": "Capture Window by Name to Clipboard OR File ", 485 | "format": "Window Name*:{$KillerBOSS.TP.Plugins.screencapture.window_name$} Save:{$KillerBOSS.TP.Plugins.screencapture.window_active_capture$} Directory->{$KillerBOSS.TP.Plugins.screencapture.filepath$} and file name ->{$KillerBOSS.TP.Plugins.screencapture.filename$} ", 486 | "data": [ 487 | { 488 | "id": "KillerBOSS.TP.Plugins.screencapture.window_name", 489 | "type": "text", 490 | "label": "text", 491 | "default": "" 492 | }, 493 | { 494 | "id": "KillerBOSS.TP.Plugins.screencapture.window_capture_type", 495 | "type": "choice", 496 | "label": "choice", 497 | "default": "3", 498 | "valueChoices": [ 499 | "0", 500 | "1", 501 | "2", 502 | "3" 503 | ] 504 | }, 505 | { 506 | "id": "KillerBOSS.TP.Plugins.screencapture.filepath", 507 | "type": "folder", 508 | "label": "folder", 509 | "default": "" 510 | }, 511 | { 512 | "id": "KillerBOSS.TP.Plugins.screencapture.filename", 513 | "type": "text", 514 | "label": "text", 515 | "default": "" 516 | }, 517 | { 518 | "id": "KillerBOSS.TP.Plugins.screencapture.window_active_capture", 519 | "type": "choice", 520 | "label": "choice", 521 | "default": "Pick One", 522 | "valueChoices": [ 523 | "Clipboard", 524 | "File" 525 | ] 526 | } 527 | ] 528 | }, 529 | { 530 | "id": "KillerBOSS.TP.Plugins.window.current", 531 | "name": "CAPTURE: Current Active Window to File / Clipboard", 532 | "prefix": "plugin", 533 | "type": "communicate", 534 | "tryInline": true, 535 | "description": "Capture CURRENT Active Window to Clipboard OR File ", 536 | "format": "Save to {$KillerBOSS.TP.Plugins.screencapture.window_active_capture$} IF file -> {$KillerBOSS.TP.Plugins.screencapture.filepath2$} and {$KillerBOSS.TP.Plugins.screencapture.filename2$}.png", 537 | "data": [ 538 | { 539 | "id": "KillerBOSS.TP.Plugins.screencapture.window_active_capture", 540 | "type": "choice", 541 | "label": "choice", 542 | "default": "Pick One", 543 | "valueChoices": [ 544 | "Clipboard", 545 | "File" 546 | ] 547 | }, 548 | { 549 | "id": "KillerBOSS.TP.Plugins.screencapture.filepath2", 550 | "type": "folder", 551 | "label": "folder", 552 | "default": "" 553 | }, 554 | { 555 | "id": "KillerBOSS.TP.Plugins.screencapture.filename2", 556 | "type": "text", 557 | "label": "text", 558 | "default": "" 559 | } 560 | ] 561 | }, 562 | 563 | { 564 | "id": "KillerBOSS.TP.Plugins.winsettings.move_window", 565 | "name": "DISPLAY: Move Current To Monitor Left/Right", 566 | "prefix": "plugin", 567 | "type": "communicate", 568 | "tryInline": true, 569 | "format": "Move Current Window {$KillerBOSS.TP.Plugins.winsettings.move_window_choice$}", 570 | "data": [ 571 | { 572 | "id": "KillerBOSS.TP.Plugins.winsettings.move_window_choice", 573 | "type": "choice", 574 | "label": "choice", 575 | "default": "Pick a Monitor", 576 | "valueChoices": ["Left", "Right"] 577 | } 578 | ] 579 | }, 580 | 581 | { 582 | "id": "KillerBOSS.TP.Plugins.winsettings.primary_monitor", 583 | "name": "DISPLAY: Change Primary Monitor", 584 | "prefix": "plugin", 585 | "type": "communicate", 586 | "tryInline": true, 587 | "format": "Change Primary Monitor To {$KillerBOSS.TP.Plugins.winsettings.primary_monitor_choice$}", 588 | "data": [ 589 | { 590 | "id": "KillerBOSS.TP.Plugins.winsettings.primary_monitor_choice", 591 | "type": "choice", 592 | "label": "primary monitor choice", 593 | "default": "", 594 | "valueChoices": [] 595 | } 596 | ] 597 | }, 598 | 599 | 600 | { 601 | "id": "KillerBOSS.TP.Plugins.winsettings.rotate_display", 602 | "name": "DISPLAY: Rotate Display / Monitor", 603 | "prefix": "plugin", 604 | "type": "communicate", 605 | "tryInline": true, 606 | "format": "Set Monitor {$KillerBOSS.TP.Plugins.winsettings.monchoice$} to {$KillerBOSS.TP.Plugins.winsettings.mon_rotate$} degrees", 607 | "data": [ 608 | { 609 | "id": "KillerBOSS.TP.Plugins.winsettings.monchoice", 610 | "type": "choice", 611 | "label": "choice", 612 | "default": "Pick a Monitor", 613 | "valueChoices": [] 614 | }, 615 | { 616 | "id": "KillerBOSS.TP.Plugins.winsettings.mon_rotate", 617 | "type": "choice", 618 | "label": "choice", 619 | "default": "0", 620 | "valueChoices": ["0", "90", "180", "270"] 621 | } 622 | ] 623 | }, 624 | { 625 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.actions", 626 | "name": "DISPLAY: Virtual Desktop: Switch/Change", 627 | "prefix": "plugin", 628 | "type": "communicate", 629 | "tryInline": true, 630 | "format": "Go to {$KillerBOSS.TP.Plugins.virtualdesktop.actionchoice$} Virtual Desktop", 631 | "data": [ 632 | { 633 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.actionchoice", 634 | "type": "choice", 635 | "label": "choice", 636 | "default": "", 637 | "valueChoices": [ 638 | "Next", 639 | "Previous" 640 | ] 641 | } 642 | ] 643 | }, 644 | { 645 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.create", 646 | "name": "DISPLAY: Virtual Desktop: Create New", 647 | "prefix": "plugin", 648 | "type": "communicate", 649 | "tryInline": true, 650 | "format": "Create Virtual Desktop with name {$KillerBOSS.TP.Plugins.virtualdesktop.create.name$}", 651 | "data": [ 652 | { 653 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.create.name", 654 | "type": "text", 655 | "label": "text", 656 | "default": "" 657 | } 658 | ] 659 | }, 660 | { 661 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.remove", 662 | "name": "DISPLAY: Virtual Desktop: Remove", 663 | "prefix": "plugin", 664 | "type": "communicate", 665 | "tryInline": true, 666 | "format": "Remove Virtual Desktop {$KillerBOSS.TP.Plugins.virtualdesktop.actionchoice$}", 667 | "data": [ 668 | { 669 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.actionchoice", 670 | "type": "choice", 671 | "label": "choice", 672 | "default": "", 673 | "valueChoices": [] 674 | }, 675 | { 676 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.remove.fallback", 677 | "type": "choice", 678 | "label": "Fall Back Choice", 679 | "default": "", 680 | "valueChoices": [] 681 | } 682 | ] 683 | }, 684 | { 685 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.rename", 686 | "name": "DISPLAY: Virtual Desktop: Rename", 687 | "prefix": "plugin", 688 | "type": "communicate", 689 | "tryInline": true, 690 | "format": "Rename {$KillerBOSS.TP.Plugins.virtualdesktop.actionchoice$} with name {$KillerBOSS.TP.Plugins.virtualdesktop.create.rename$}", 691 | "data": [ 692 | { 693 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.create.rename", 694 | "type": "text", 695 | "label": "text", 696 | "default": "" 697 | }, 698 | { 699 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.actionchoice", 700 | "type": "choice", 701 | "label": "choice", 702 | "default": "", 703 | "valueChoices": [] 704 | } 705 | ] 706 | }, 707 | { 708 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.actions.move_window", 709 | "name": "DISPLAY: Virtual Desktop: Move Current to #", 710 | "prefix": "plugin", 711 | "type": "communicate", 712 | "tryInline": true, 713 | "description": "Move Current Active Window to Virtual Desktop desired", 714 | "format": "{$KillerBOSS.TP.Plugins.virtualdesktop.actionchoice$} Pin it -> {$KillerBOSS.TP.Plugins.virtualdesktop.actionchoice.pinned$}", 715 | "data": [ 716 | { 717 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.actionchoice", 718 | "type": "choice", 719 | "label": "choice", 720 | "default": "", 721 | "valueChoices": [] 722 | }, 723 | { 724 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.actionchoice.pinned", 725 | "type": "choice", 726 | "label": "choice", 727 | "default": "False", 728 | "valueChoices": [ 729 | "True", 730 | "False" 731 | ] 732 | } 733 | ] 734 | }, 735 | 736 | { 737 | "id": "KillerBOSS.TP.Plugins.winsettings.shutdown", 738 | "name": "UTILITY: Shutdown Computer in (x)", 739 | "prefix": "plugin", 740 | "type": "communicate", 741 | "tryInline": true, 742 | "format": "Shutdown Computer in {$KillerBOSS.TP.Plugins.winsettings.shutdown_minutes$} MINUTES", 743 | "data": [ 744 | { 745 | "id": "KillerBOSS.TP.Plugins.winsettings.shutdown_minutes", 746 | "type": "text", 747 | "label": "text", 748 | "default": "" 749 | } 750 | ] 751 | }, 752 | 753 | { 754 | "id": "KillerBOSS.TP.Plugins.winsettings.powerplan", 755 | "name": "UTILITY: Change Powerplan", 756 | "prefix": "plugin", 757 | "type": "communicate", 758 | "tryInline": true, 759 | "format": "Change Windows Powerplan to {$KillerBOSS.TP.Plugins.winsettings.powerplan_choice$}", 760 | "data": [ 761 | { 762 | "id": "KillerBOSS.TP.Plugins.winsettings.powerplan_choice", 763 | "type": "choice", 764 | "label": "pplan choice", 765 | "default": "", 766 | "valueChoices": [] 767 | } 768 | ] 769 | }, 770 | 771 | { 772 | "id": "KillerBOSS.TP.Plugins.winsettings.action", 773 | "name": "UTILITY: System Settings", 774 | "prefix": "plugin", 775 | "type": "communicate", 776 | "tryInline": true, 777 | "format": "Open: {$KillerBOSS.TP.Plugins.winsettings.choice$} settings section", 778 | "data": [ 779 | { 780 | "id": "KillerBOSS.TP.Plugins.winsettings.choice", 781 | "type": "choice", 782 | "label": "choice", 783 | "default": "SYSTEM: Settings Home Page", 784 | "valueChoices": [] 785 | } 786 | ] 787 | }, 788 | 789 | { 790 | "id": "KillerBOSS.TP.Plugins.toast.create", 791 | "name": "UTILITY: Windows Notification", 792 | "prefix": "plugin", 793 | "type": "communicate", 794 | "tryInline": true, 795 | "description": "Create Windows Notification / Toast", 796 | "format": "Title:{$KillerBOSS.TP.Plugins.toast.title$} Message:{$KillerBOSS.TP.Plugins.toast.message$} Duration:{$KillerBOSS.TP.Plugins.toast.duration$} Icon(optional) {$KillerBOSS.TP.Plugins.toast.iconpath$} Sound:{$KillerBOSS.TP.Plugins.toast.audio$} Button-Text(optional):{$KillerBOSS.TP.Plugins.toast.buttontext$} Button-Link(When Clicked):{$KillerBOSS.TP.Plugins.toast.buttonlink$}", 797 | "data": [ 798 | { 799 | "id": "KillerBOSS.TP.Plugins.toast.title", 800 | "type": "text", 801 | "label": "text", 802 | "default": "" 803 | }, 804 | { 805 | "id": "KillerBOSS.TP.Plugins.toast.message", 806 | "type": "text", 807 | "label": "text", 808 | "default": "" 809 | }, 810 | { 811 | "id": "KillerBOSS.TP.Plugins.toast.duration", 812 | "type": "choice", 813 | "label": "choice", 814 | "default": "Short", 815 | "valueChoices": [ 816 | "Short", 817 | "Long" 818 | ] 819 | }, 820 | { 821 | "id": "KillerBOSS.TP.Plugins.toast.buttontext", 822 | "type": "text", 823 | "label": "text", 824 | "default": "" 825 | }, 826 | { 827 | "id": "KillerBOSS.TP.Plugins.toast.buttonlink", 828 | "type": "text", 829 | "label": "text", 830 | "default": "" 831 | }, 832 | { 833 | "id": "KillerBOSS.TP.Plugins.toast.iconpath", 834 | "type": "file", 835 | "label": "file", 836 | "extensions": ["*.jpg","*.png", "*.ico"], 837 | "default": "" 838 | }, 839 | { 840 | "id": "KillerBOSS.TP.Plugins.toast.audio", 841 | "type": "choice", 842 | "label": "choice", 843 | "default": "Default", 844 | "valueChoices": [ 845 | "Default", 846 | "IM", 847 | "Mail", 848 | "Reminder", 849 | "SMS", 850 | "LoopingAlarm1", 851 | "LoopingAlarm2", 852 | "LoopingAlarm3", 853 | "LoopingAlarm4", 854 | "LoopingAlarm5", 855 | "LoopingAlarm6", 856 | "LoopingAlarm7", 857 | "LoopingAlarm8", 858 | "LoopingCall1", 859 | "LoopingCall2", 860 | "LoopingCall3", 861 | "LoopingCall4", 862 | "LoopingCall5", 863 | "LoopingCall6", 864 | "LoopingCall7", 865 | "LoopingCall8", 866 | "LoopingCall9", 867 | "LoopingCall10", 868 | "Silent" 869 | ] 870 | } 871 | ] 872 | }, 873 | { 874 | "id": "KillerBOSS.TP.Plugins.magnifier.actions", 875 | "name": "UTILITY: Magnifier Glass", 876 | "prefix": "plugin", 877 | "type": "communicate", 878 | "tryInline": true, 879 | "format": "Magnifier Glass: {$KillerBOSS.TP.Plugins.magnifier.actionchoice$} ", 880 | "data": [ 881 | { 882 | "id": "KillerBOSS.TP.Plugins.magnifier.actionchoice", 883 | "type": "choice", 884 | "label": "choice", 885 | "default": "", 886 | "valueChoices": [ 887 | "Zoom In", 888 | "Zoom Out", 889 | "Exit", 890 | "Dock", 891 | "Lens", 892 | "Full Screen", 893 | "Invert Colors" 894 | ] 895 | } 896 | ] 897 | }, 898 | { 899 | "id": "KillerBOSS.TP.Plugins.magnifier.onHold.actions", 900 | "name": "UTILITY: Magnifier Glass Adjustment", 901 | "prefix": "plugin", 902 | "type": "communicate", 903 | "tryInline": true, 904 | "hasHoldFunctionality": true, 905 | "description": "IF ON HOLD -> Increment by X \nIF ON PRESS -> Set to X", 906 | "format": "Select {$KillerBOSS.TP.Plugins.magnifier.lens.choice$} and set/adjust by {$KillerBOSS.TP.Plugins.magnifier.lensIncrement$} ", 907 | "data": [ 908 | { 909 | "id": "KillerBOSS.TP.Plugins.magnifier.lens.choice", 910 | "type": "choice", 911 | "label": "choice", 912 | "default": "", 913 | "valueChoices": [ 914 | "Lens X", 915 | "Lens Y", 916 | "Zoom" 917 | ] 918 | }, 919 | { 920 | "id": "KillerBOSS.TP.Plugins.magnifier.lensIncrement", 921 | "type": "text", 922 | "label": "text", 923 | "allowDecimals": false, 924 | "minValue":5, 925 | "maxValue":1600, 926 | "default": "5" 927 | } 928 | ] 929 | }, 930 | { 931 | "id": "KillerBOSS.TP.Plugins.winextra.keyboard", 932 | "name": "UTILITY: On-Screen Keyboard", 933 | "prefix": "plugin", 934 | "type": "communicate", 935 | "tryInline": true, 936 | "format": "Toggle On-Screen Keyboard", 937 | "data": [ 938 | { 939 | "id": "KillerBOSS.TP.Plugins.winextra.action", 940 | "type": "text", 941 | "label": "text", 942 | "default": "" 943 | } 944 | ] 945 | }, 946 | { 947 | "id": "KillerBOSS.TP.Plugins.winextra.emojipanel", 948 | "name": "UTILITY: Emoji Panel", 949 | "prefix": "plugin", 950 | "type": "communicate", 951 | "tryInline": true, 952 | "format": "Open Emoji Panel" 953 | }, 954 | 955 | { 956 | "id": "KillerBOSS.TP.Plugins.capture.clipboard", 957 | "name": "UTILITY: Text / Value to Clipboard", 958 | "prefix": "plugin", 959 | "type": "communicate", 960 | "tryInline": true, 961 | "format": "Copy {$KillerBOSS.TP.Plugins.capture.clipboard.contents$} to clipboard", 962 | "data": [ 963 | { 964 | "id": "KillerBOSS.TP.Plugins.capture.clipboard.contents", 965 | "type": "text", 966 | "label": "text", 967 | "default": "" 968 | } 969 | ] 970 | }, 971 | 972 | { 973 | "id": "KillerBOSS.TP.Plugins.capture.clipboard.toValue", 974 | "name": "UTILITY: Paste Clipboard Contents to Value", 975 | "prefix": "plugin", 976 | "type": "communicate", 977 | "tryInline": true, 978 | "description": "Usage Notes: Remove Brackets from Value Name EXAMPLE: (${value:AD3_desc} -> AD3_desc", 979 | "format": "Save Clipboard to value {$KillerBOSS.TP.Plugins.capture.clipboard.contents.toValue$}", 980 | "data": [ 981 | { 982 | "id": "KillerBOSS.TP.Plugins.capture.clipboard.contents.toValue", 983 | "type": "text", 984 | "label": "text", 985 | "default": "" 986 | } 987 | ] 988 | }, 989 | { 990 | "id": "KillerBOSS.TP.Plugins.TextToSpeech.speak", 991 | "name": "UTILITY: Text To Speech: Speak X", 992 | "prefix": "plugin", 993 | "type": "communicate", 994 | "description": "Play Text to Speech thru a specific Audio Output", 995 | "tryInline": true, 996 | "format": "Text:{$KillerBOSS.TP.Plugins.TextToSpeech.text$} Voice: {$KillerBOSS.TP.Plugins.TextToSpeech.voices$} Volume:{$KillerBOSS.TP.Plugins.TextToSpeech.volume$} Speech Rate:{$KillerBOSS.TP.Plugins.TextToSpeech.rate$} OUTPUT:{$KillerBOSS.TP.Plugins.TextToSpeech.output$}", 997 | "data": [ 998 | { 999 | "id": "KillerBOSS.TP.Plugins.TextToSpeech.voices", 1000 | "type": "choice", 1001 | "label": "choice", 1002 | "default": "", 1003 | "valueChoices": [] 1004 | }, 1005 | { 1006 | "id": "KillerBOSS.TP.Plugins.TextToSpeech.text", 1007 | "type": "text", 1008 | "label": "text", 1009 | "default": "Hello!" 1010 | }, 1011 | { 1012 | "id": "KillerBOSS.TP.Plugins.TextToSpeech.volume", 1013 | "type": "number", 1014 | "label": "tts volume", 1015 | "allowDecimals": false, 1016 | "default": "100", 1017 | "minValue":0, 1018 | "maxValue":100 1019 | }, 1020 | { 1021 | "id": "KillerBOSS.TP.Plugins.TextToSpeech.rate", 1022 | "type": "number", 1023 | "label": "tts rate", 1024 | "allowDecimals": false, 1025 | "default": "175", 1026 | "minValue":25, 1027 | "maxValue":600 1028 | }, 1029 | { 1030 | "id": "KillerBOSS.TP.Plugins.TextToSpeech.output", 1031 | "type": "choice", 1032 | "label": "tts output choice", 1033 | "default": "", 1034 | "valueChoices":[] 1035 | } 1036 | ] 1037 | }, 1038 | { 1039 | "id": "KillerBOSS.TP.Plugins.TextToSpeech.stop", 1040 | "name": "UTILITY: Text to Speech: Stop", 1041 | "prefix": "plugin", 1042 | "type": "communicate", 1043 | "tryInline": true, 1044 | "format": "Stop TextToSpeech" 1045 | } 1046 | ], 1047 | "events": [ 1048 | { 1049 | "id": "KillerBOSS.TP.Plugins.events.default_outputdevice", 1050 | "name": "When Default Output Device changes", 1051 | "format": "When Default Output Device changes $val", 1052 | "type": "communicate", 1053 | "valueChoices": [ 1054 | "True" 1055 | ], 1056 | "valueType": "choice", 1057 | "valueStateId": "KillerBOSS.TP.Plugins.state.default_outputdevice" 1058 | }, 1059 | { 1060 | "id": "KillerBOSS.TP.Plugins.events.default_inputdevice", 1061 | "name": "When Default Input Device changes", 1062 | "format": "When Default Input Device changes $val", 1063 | "type": "communicate", 1064 | "valueChoices": [ 1065 | "True" 1066 | ], 1067 | "valueType": "choice", 1068 | "valueStateId": "KillerBOSS.TP.Plugins.state.default_inputdevice" 1069 | }, 1070 | { 1071 | "id": "KillerBOSS.TP.Plugins.events.clipboard_contents", 1072 | "name": "When Clipboard Contents Change", 1073 | "format": "When Clipboard Contents Change $val", 1074 | "type": "communicate", 1075 | "valueChoices": [ 1076 | "True" 1077 | ], 1078 | "valueType": "choice", 1079 | "valueStateId": "KillerBOSS.TP.Plugins.capture.clipboard.contents" 1080 | } 1081 | ], 1082 | "states": [ 1083 | { 1084 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.MousePos.X", 1085 | "type": "text", 1086 | "desc": "Advance Mouse: Current Mouse X pos", 1087 | "default": "0" 1088 | }, 1089 | { 1090 | "id": "KillerBOSS.TP.Plugins.AdvanceMouse.MousePos.Y", 1091 | "type": "text", 1092 | "desc": "Advance Mouse: Current Mouse Y pos", 1093 | "default": "0" 1094 | }, 1095 | { 1096 | "id": "KillerBOSS.TP.Plugins.winsettings.state.active.mouseCapture", 1097 | "type": "text", 1098 | "desc": "Active Mouse Capture", 1099 | "default": "" 1100 | }, 1101 | { 1102 | "id": "KillerBOSS.TP.Plugins.Sound.CurrentOutputDevice", 1103 | "type": "text", 1104 | "desc": "Sound: Get Current Output Device", 1105 | "default": "None" 1106 | }, 1107 | { 1108 | "id": "KillerBOSS.TP.Plugins.Sound.CurrentInputDevice", 1109 | "type": "text", 1110 | "desc": "Sound: Get Current Input Device", 1111 | "default": "None" 1112 | }, 1113 | { 1114 | "id": "KillerBOSS.TP.Plugins.Application.currentFocusedAPP", 1115 | "type": "text", 1116 | "desc": "Application get current focused APP", 1117 | "default": "None" 1118 | }, 1119 | { 1120 | "id": "KillerBOSS.TP.Plugins.windows.network.received", 1121 | "type": "text", 1122 | "desc": "Network: Total Bytes Received", 1123 | "default": "" 1124 | }, 1125 | { 1126 | "id": "KillerBOSS.TP.Plugins.windows.network.sent", 1127 | "type": "text", 1128 | "desc": "Network: Total Bytes Sent", 1129 | "default": "" 1130 | }, 1131 | { 1132 | "id": "KillerBOSS.TP.Plugins.windows.disk.read", 1133 | "type": "text", 1134 | "desc": "Disk: Total Read", 1135 | "default": "" 1136 | }, 1137 | { 1138 | "id": "KillerBOSS.TP.Plugins.windows.disk.write", 1139 | "type": "text", 1140 | "desc": "Disk: Total Write", 1141 | "default": "" 1142 | }, 1143 | { 1144 | "id": "KillerBOSS.TP.Plugins.virtualdesktop.current_vd", 1145 | "type": "text", 1146 | "desc": "Curent Virtual Desktop", 1147 | "default": "" 1148 | }, 1149 | { 1150 | "id": "KillerBOSS.TP.Plugins.Windows.activeCOUNT", 1151 | "type": "text", 1152 | "desc": "Active Window Count", 1153 | "default": "" 1154 | }, 1155 | { 1156 | "id": "KillerBOSS.TP.Plugins.winsettings.powerplan_current", 1157 | "type": "text", 1158 | "desc": "Active Power Plan", 1159 | "default": "" 1160 | }, 1161 | { 1162 | "id": "KillerBOSS.TP.Plugins.Windows.livetime", 1163 | "type": "text", 1164 | "desc": "Computer Uptime", 1165 | "default": "" 1166 | }, 1167 | { 1168 | "id": "KillerBOSS.TP.Plugins.capture.clipboard.contents", 1169 | "type": "text", 1170 | "desc": "Clipboard Contents", 1171 | "default": "" 1172 | } 1173 | ] 1174 | } 1175 | ], 1176 | "settings": [ 1177 | { 1178 | "name": "Update Interval: Public IP", 1179 | "type": "number", 1180 | "default": "240", 1181 | "maxValue": 1800, 1182 | "minValue": 0, 1183 | "allowDecimals": false, 1184 | "readOnly": false 1185 | }, 1186 | { 1187 | "name": "Update Interval: Hard Drive", 1188 | "type": "number", 1189 | "default": "60", 1190 | "maxValue": 1800, 1191 | "minValue": 0, 1192 | "allowDecimals": false, 1193 | "readOnly": false 1194 | }, 1195 | { 1196 | "name": "Update Interval: Active Monitors", 1197 | "type": "number", 1198 | "default": "240", 1199 | "maxValue": 1800, 1200 | "minValue": 0, 1201 | "allowDecimals": false, 1202 | "readOnly": false 1203 | }, 1204 | { 1205 | "name": "Update Interval: Active Windows", 1206 | "type": "number", 1207 | "default": "10", 1208 | "maxValue": 1800, 1209 | "minValue": 5, 1210 | "allowDecimals": false, 1211 | "readOnly": false 1212 | }, 1213 | { 1214 | "name": "Update Interval: Active Virtual Desktops", 1215 | "type": "number", 1216 | "default": "15", 1217 | "maxValue": 1800, 1218 | "minValue": 5, 1219 | "allowDecimals": false, 1220 | "readOnly": false 1221 | }, 1222 | { 1223 | "name": "Clipboard Listener (ON / OFF)", 1224 | "type": "text", 1225 | "default": "ON", 1226 | "readOnly": false 1227 | }, 1228 | { 1229 | "name": "Audio State Exemption List", 1230 | "type": "text", 1231 | "default": "Enter '.exe' name seperated by a comma for more than 1", 1232 | "readOnly": false 1233 | }, 1234 | { 1235 | "name": "DEBUG MODE / LOGGING", 1236 | "type": "text", 1237 | "description": "Wish we could write descript here", 1238 | "default": "OFF", 1239 | "readOnly": false 1240 | } 1241 | ] 1242 | } 1243 | -------------------------------------------------------------------------------- /src/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KillerBOSS2019/WinTools/d5cbbe721b5ff150e7b3a4afe9dca41a82c31ca5/src/icon.ico -------------------------------------------------------------------------------- /src/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KillerBOSS2019/WinTools/d5cbbe721b5ff150e7b3a4afe9dca41a82c31ca5/src/icon.png -------------------------------------------------------------------------------- /src/main.py: -------------------------------------------------------------------------------- 1 | from asyncio.log import logger 2 | from time import sleep 3 | from turtle import title 4 | from urllib.request import urlopen 5 | from utils.util import * 6 | 7 | import mss.tools 8 | import pygetwindowmp as pygetwindow 9 | import schedule 10 | import TouchPortalAPI 11 | from TouchPortalAPI import TYPES, Tools 12 | from screeninfo import get_monitors 13 | import logging 14 | 15 | def debug_activate(): 16 | print("-"*30, "DEBUG MODE ON", "-"*30) 17 | Log_Format = "%(levelname)s %(asctime)s - %(message)s" 18 | logging.basicConfig(filename = "logfile.log", 19 | filemode = "w", 20 | format = Log_Format, 21 | level = logging.DEBUG) 22 | logger = logging.getLogger() 23 | 24 | 25 | 26 | 27 | 28 | ########################################################################## 29 | #____________________THE START OF WIN CALLBACK THINGS____________________# 30 | global_states = [] 31 | first_time=True 32 | class WinAudioCallBack(MagicSession): 33 | def __init__(self): 34 | global global_states, first_time 35 | super().__init__(volume_callback=self.update_volume, 36 | mute_callback=self.update_mute, 37 | state_callback=self.update_state) 38 | 39 | # ______________ DISPLAY NAME ______________ 40 | self.app_name = self.magic_root_session.app_exec 41 | print(f":: new session: {self.app_name}") 42 | 43 | if first_time: 44 | global_states.append("Master Volume") 45 | global_states.append("Current app") 46 | first_time = False 47 | if self.app_name not in audio_exempt_list: 48 | # set initial: 49 | self.update_mute(self.mute) 50 | self.update_state(self.state) 51 | self.update_volume(self.volume) 52 | 53 | 54 | def update_state(self, new_state): 55 | """ 56 | when status changed 57 | (see callback -> AudioSessionEvents -> OnStateChanged) 58 | """ 59 | if self.app_name not in audio_exempt_list: 60 | if new_state == AudioSessionState.Inactive: 61 | # AudioSessionStateInactive 62 | """Sesssion is Inactive""" 63 | print(f"{self.app_name} not active") 64 | TPClient.stateUpdate(f'KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{self.app_name}.active',"False") 65 | 66 | elif new_state == AudioSessionState.Active: 67 | """Session Active""" 68 | print(f"{self.app_name} is an Active Session") 69 | TPClient.stateUpdate(f'KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{self.app_name}.active',"True") 70 | 71 | elif new_state == AudioSessionState.Expired: 72 | """Removing Expired States""" 73 | check_states(self.app_name, remove=True) 74 | 75 | 76 | def update_volume(self, new_volume): 77 | """ 78 | when volume is changed externally - Updating Sliders and Volume States 79 | (see callback -> AudioSessionEvents -> OnSimpleVolumeChanged ) 80 | """ 81 | if self.app_name not in audio_exempt_list: 82 | TPClient.stateUpdate(f'KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{self.app_name}',str(round(new_volume*100))) 83 | print("NEW VOLUME", str(round(new_volume*100))) 84 | TPClient.send({ 85 | "type":"connectorUpdate", 86 | "connectorId":f"pc_Windows-Tools_KillerBOSS.TP.Plugins.VolumeMixer.connectors.APPcontrol|KillerBOSS.TP.Plugins.VolumeMixer.slidercontrol={self.app_name}", 87 | "value": round(new_volume*100) 88 | }) 89 | 90 | """Checking for Current App If Its Active, Adjust it also""" 91 | activeWindow = getActiveExecutablePath() 92 | if activeWindow != "": 93 | if os.path.basename(activeWindow) == self.app_name: 94 | TPClient.send({ 95 | "type":"connectorUpdate", 96 | "connectorId":f"pc_Windows-Tools_KillerBOSS.TP.Plugins.VolumeMixer.connectors.APPcontrol|KillerBOSS.TP.Plugins.VolumeMixer.slidercontrol=Current app", 97 | "value": round(new_volume*100) 98 | }) 99 | 100 | 101 | 102 | def update_mute(self, muted): 103 | """ when mute state is changed by user or through other app """ 104 | 105 | if self.app_name not in audio_exempt_list: 106 | check_states(self.app_name) 107 | time.sleep(0.1) 108 | 109 | if muted: 110 | print(f"{self.app_name} is unmuted") 111 | TPClient.stateUpdate(f"KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{self.app_name}.muteState", "Muted") 112 | # TPClient.stateUpdate("KillerBOSS.TP.Plugins.state.test", "True") 113 | else: 114 | print(f"{self.app_name} is muted") 115 | TPClient.stateUpdate(f"KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{self.app_name}.muteState", "Un-Muted") 116 | # TPClient.stateUpdate("KillerBOSS.TP.Plugins.state.test", "False") 117 | #______ ______________________THE END OF CALLBACK_________________________# 118 | ########################################################################## 119 | 120 | 121 | 122 | def run_continuously(interval=1): 123 | cease_continuous_run = threading.Event() 124 | 125 | class ScheduleThread(threading.Thread): 126 | @classmethod 127 | def run(cls): 128 | while not cease_continuous_run.is_set(): 129 | schedule.run_pending() 130 | time.sleep(interval) 131 | 132 | continuous_thread = ScheduleThread() 133 | continuous_thread.setDaemon(True) 134 | continuous_thread.start() 135 | return cease_continuous_run 136 | 137 | 138 | 139 | def check_states(app_name, remove=False): 140 | global global_states 141 | print("AUDIO EXEMPT LIST", audio_exempt_list) 142 | 143 | if app_name not in global_states: 144 | print("The Global States", global_states) 145 | TPClient.createStateMany([ 146 | { 147 | "id": f'KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{app_name}.muteState', 148 | "desc": f"{app_name} Mute State", 149 | "value": "" 150 | }, 151 | { 152 | "id": f'KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{app_name}', 153 | "desc": f"{app_name} Volume", 154 | "value": "" 155 | }, 156 | { 157 | "id": f'KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{app_name}.active', 158 | "desc": f"{app_name} Active", 159 | "value": "" 160 | }, 161 | ]) 162 | global_states.append(app_name) 163 | 164 | 165 | 166 | """UPDATING CHOICES WITH GLOBALS""" 167 | TPClient.choiceUpdate('KillerBOSS.TP.Plugins.VolumeMixer.Increase/DecreaseVolume.process', global_states) 168 | TPClient.choiceUpdate('KillerBOSS.TP.Plugins.VolumeMixer.Mute/Unmute.process', global_states) 169 | TPClient.choiceUpdate("KillerBOSS.TP.Plugins.VolumeMixer.slidercontrol", global_states) 170 | print("new State Added") 171 | time.sleep(0.1) 172 | 173 | """ Checking for Exempt Audio""" 174 | if app_name in audio_exempt_list: 175 | TPClient.removeStateMany([f"KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{app_name}.muteState", f"KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{app_name}",f"KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{app_name}.active"]) 176 | global_states.remove(app_name) 177 | print("was in exempt list, so we are removing its state") 178 | 179 | if remove: 180 | """ Deleting Volume States As Needed """ 181 | TPClient.removeStateMany([f"KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{app_name}.muteState", f"KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{app_name}",f"KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{app_name}.active"]) 182 | global_states.remove(app_name) 183 | 184 | TPClient.choiceUpdate('KillerBOSS.TP.Plugins.VolumeMixer.Increase/DecreaseVolume.process', global_states) 185 | TPClient.choiceUpdate('KillerBOSS.TP.Plugins.VolumeMixer.Mute/Unmute.process', global_states) 186 | TPClient.choiceUpdate("KillerBOSS.TP.Plugins.VolumeMixer.slidercontrol", global_states) 187 | print(f":: closed session: {app_name}") 188 | 189 | 190 | 191 | def timebooted_loop(): 192 | """This is on threaded loop instead of schedule so its more consistant""" 193 | ##Getting Boot Time once, then calculating current time against it indefiniately 194 | boot_time = psutil.boot_time() 195 | while True: 196 | TPClient.stateUpdate("KillerBOSS.TP.Plugins.Windows.livetime", str(time_booted(boot_time))) 197 | time.sleep(1) 198 | 199 | 200 | old_vd = [] 201 | def vd_check(): 202 | global old_vd 203 | vdlist=[] 204 | vdlist.append("Next") 205 | vdlist.append("Previous") 206 | virtual_desks = get_virtual_desktops() 207 | for item in virtual_desks: 208 | if not item.name: 209 | vdlist.append(f"[{item.number}] Desktop {item.number}") 210 | else: 211 | vdlist.append(f"[{item.number}] {item.name}") 212 | if vdlist != old_vd: 213 | TPClient.choiceUpdate("KillerBOSS.TP.Plugins.virtualdesktop.actionchoice", vdlist) 214 | old_vd = vdlist 215 | 216 | 217 | ## should we bother checking old IP info to new to see if its different before we update states? 218 | def get_ip_loop(): 219 | try: 220 | pub_ip =get_ip_details("choice1") 221 | for item in pub_ip: 222 | TPClient.stateUpdate(f"KillerBOSS.TP.Plugins.publicip.{item}", pub_ip[item]) 223 | except: 224 | pass 225 | 226 | 227 | global count 228 | count = 0 229 | def disk_usage(): 230 | global count 231 | thedrivenames = get_win_drive_names2() 232 | partitions = psutil.disk_partitions() 233 | drives = False 234 | count = count + 1 235 | print(f"================[ {count} ]==============") 236 | try: 237 | for partition in partitions: 238 | the_partition = partition.device.split(":") 239 | driveletter = (the_partition[0]) 240 | if not drives: 241 | if partition.mountpoint[:2] in thedrivenames: 242 | the_drive_name = thedrivenames[partition.mountpoint[:2]] 243 | partition_usage = psutil.disk_usage(partition.mountpoint) 244 | percentage = 100 - partition_usage.percent 245 | str_percent = str(percentage)[0:4] 246 | driveletter = partition.mountpoint[:1] 247 | 248 | 249 | TPClient.createStateMany([ 250 | { 251 | "id": f'KillerBOSS.TP.Plugins.Windows.drive.letter_{driveletter}', 252 | "desc": f"Drive {driveletter}: Name", 253 | "value": "" 254 | }, 255 | { 256 | "id": f'KillerBOSS.TP.Plugins.Windows.drive.size_{driveletter}', 257 | "desc": f"Drive {driveletter}: Total Space", 258 | "value": "" 259 | }, 260 | { 261 | "id": f'KillerBOSS.TP.Plugins.Windows.drive.free_{driveletter}', 262 | "desc": f"Drive {driveletter}: Free Space", 263 | "value": "" 264 | }, 265 | { 266 | "id": f'KillerBOSS.TP.Plugins.Windows.drive.percent_{driveletter}', 267 | "desc": f"Drive {driveletter}: Used", 268 | "value": "" 269 | }, 270 | { 271 | "id": f'KillerBOSS.TP.Plugins.Windows.drive.percent_{driveletter}', 272 | "desc": f"Drive {driveletter}: Percentage", 273 | "value": "" 274 | }, 275 | ]) 276 | 277 | 278 | TPClient.stateUpdateMany([ 279 | { 280 | "id": f'KillerBOSS.TP.Plugins.Windows.drive.letter_{driveletter}', 281 | "value": str(the_drive_name) 282 | }, 283 | { 284 | "id": f'KillerBOSS.TP.Plugins.Windows.drive.size_{driveletter}', 285 | "value": str(get_size(partition_usage.total)) 286 | }, 287 | { 288 | "id": f'KillerBOSS.TP.Plugins.Windows.drive.free_{driveletter}', 289 | "value": str(get_size(partition_usage.free).replace("GB","")) 290 | }, 291 | { 292 | "id": f'KillerBOSS.TP.Plugins.Windows.drive.used_{driveletter}', 293 | "value": str(get_size(partition_usage.used).replace("GB","")) 294 | }, 295 | { 296 | "id": f'KillerBOSS.TP.Plugins.Windows.drive.percent_{driveletter}', 297 | "value": str(str_percent) 298 | }, 299 | ]) 300 | except Exception as e: 301 | print("Disk usage", e) 302 | 303 | ### Total Read/Write since boot 304 | # get IO statistics since boot 305 | try: 306 | disk_io = psutil.disk_io_counters() 307 | 308 | network = network_usage() 309 | 310 | TPClient.stateUpdateMany([ 311 | { 312 | "id": f'KillerBOSS.TP.Plugins.windows.network.sent', 313 | "value": network['sent'] 314 | }, 315 | { 316 | "id": f'KillerBOSS.TP.Plugins.windows.network.received', 317 | "value": network['received'] 318 | }, 319 | { 320 | "id": f'KillerBOSS.TP.Plugins.windows.disk.read', 321 | "value": get_size(disk_io.read_bytes) 322 | }, 323 | { 324 | "id": f'KillerBOSS.TP.Plugins.windows.disk.write', 325 | "value": get_size(disk_io.write_bytes) 326 | }, 327 | ]) 328 | except Exception as e: 329 | print("error disk usage n stuff " + e) 330 | 331 | 332 | old_results = [] 333 | def get_windows_update(): 334 | global windows_active, old_results 335 | windows_active = get_windows() 336 | if len(old_results) is not len(windows_active): 337 | # windows_active = get_windows() 338 | print("Previous Count:", len(old_results), "New Count:", len(windows_active)) 339 | old_results = windows_active 340 | TPClient.choiceUpdate("KillerBOSS.TP.Plugins.screencapture.window_name", windows_active) 341 | TPClient.stateUpdate("KillerBOSS.TP.Plugins.Windows.activeCOUNT", str(len(windows_active))) 342 | else: 343 | windows_active = get_windows() 344 | old_results = windows_active 345 | 346 | 347 | 348 | monitor_count_old = "" 349 | def check_number_of_monitors(): 350 | global monitor_count_old 351 | mon_length = len(get_monitors()) ### Wonder if triggering this each time to get length of monitors is better / less resources than using get_monitors2 ? this uses screeninfo module 352 | if monitor_count_old != mon_length: 353 | list_monitor_full = get_monitors2() 354 | TPClient.choiceUpdate("KillerBOSS.TP.Plugins.winsettings.monchoice", list_monitor_full) 355 | TPClient.choiceUpdate("KillerBOSS.TP.Plugins.winsettings.primary_monitor_choice", list_monitor_full) 356 | list_monitor_full.insert(0, "0: ALL MONITORS") 357 | TPClient.choiceUpdate("KillerBOSS.TP.Plugins.screencapture.monitors", list_monitor_full) # KillerBOSS.TP.Plugins.screencapture.full.file 358 | monitor_count_old = mon_length 359 | 360 | 361 | def screenshot_monitor(monitor_number, filename="", clipboard = False): 362 | monitor_number = int(monitor_number.split(":")[0]) 363 | with mss.mss() as sct: 364 | try: 365 | mon = sct.monitors[monitor_number] 366 | # Capturing Entire Monitor 367 | monitor = { 368 | "top": mon["top"], 369 | "left": mon["left"], 370 | "width": mon["width"], 371 | "height": mon["height"], 372 | "mon": monitor_number, 373 | } 374 | # Grab the Image 375 | sct_img = sct.grab(monitor) 376 | 377 | if clipboard == True: 378 | """Having to Save to Temp File To Capture All Screens Successfully.. Investigate why""" 379 | if monitor_number==0: 380 | print("capturing all, using temp file") 381 | mss.tools.to_png(sct_img.rgb, sct_img.size, output="temp.png") 382 | file_to_bytes("temp.png") ## Saved to Clipboard 383 | 384 | elif monitor_number != 0: 385 | img = Image.frombytes("RGB", sct_img.size, sct_img.bgra, "raw", "BGRX") ## Instead of making a temp file we get it direct from raw to clipboard 386 | copy_im_to_clipboard(img) 387 | # TPClient.stateUpdate("KillerBOSS.TP.Plugins.winsettings.winsettings.publicIP", getFrame_base64(img).decode()) 388 | 389 | if clipboard == False: 390 | mss.tools.to_png(sct_img.rgb, sct_img.size, output=filename + ".png") 391 | print("Image saved -> "+ filename+ ".png" ) 392 | 393 | except IndexError: 394 | print("This Monitor does not exist") 395 | 396 | 397 | prev_input = "" 398 | prev_output = "" 399 | def get_default_input_output(powershell=True): 400 | global prev_input, prev_output 401 | """Getting Default Audio From SD instead of Powershell - Less CPU usage?""" 402 | if not powershell: 403 | sd._terminate() 404 | sd._initialize() 405 | default_devices = sd.default.device 406 | try: 407 | default_input = sd.query_devices(device=default_devices[0])['name'] 408 | except sd.PortAudioError as err: 409 | default_input = "No Default Output Device" 410 | print("No Default Device Set") 411 | try: 412 | default_output = sd.query_devices(device=default_devices[0])['name'] 413 | except sd.PortAudioError as err: 414 | print("No Default Device Set") 415 | default_output = "No Default Input Device" 416 | ## Input 417 | if prev_input != default_input: 418 | print("Updated default Input") 419 | TPClient.stateUpdate("KillerBOSS.TP.Plugins.state.default_inputputdevice", "True") 420 | TPClient.stateUpdate('KillerBOSS.TP.Plugins.Sound.CurrentInputDevice', str(default_input)) 421 | TPClient.stateUpdate("KillerBOSS.TP.Plugins.state.default_inputputdevice", "False") 422 | prev_input = default_input 423 | ## Output 424 | if prev_output != default_output: 425 | print("Updated default Output") 426 | TPClient.stateUpdate("KillerBOSS.TP.Plugins.state.default_outputdevice", "True") 427 | TPClient.stateUpdate('KillerBOSS.TP.Plugins.Sound.CurrentOutputDevice', str(default_output)) 428 | TPClient.stateUpdate("KillerBOSS.TP.Plugins.state.default_outputdevice", "False") 429 | prev_output = default_output 430 | 431 | """Imported from Util.py instead""" 432 | #TPClient = TouchPortalAPI.Client('Windows-Tools') 433 | 434 | 435 | 436 | 437 | 438 | global Timer 439 | running = False 440 | updateXY = True 441 | counter = 0 442 | 443 | def updateStates(): 444 | global global_states, Timer, counter 445 | Timer = threading.Timer(0.5, updateStates) 446 | Timer.start() 447 | if running: 448 | counter = counter + 1 449 | if counter%2 == 0: 450 | """ 451 | Updates every 5 loops 452 | """ 453 | 454 | try: 455 | TPClient.stateUpdate("KillerBOSS.TP.Plugins.Application.currentFocusedAPP", pygetwindow.getActiveWindowTitle()) 456 | except: 457 | pass 458 | 459 | # """ Getting App Icon""" 460 | # activeWindow = getActiveExecutablePath() 461 | # TPClient.stateUpdate("KillerBOSS.TP.Plugins.Application.currentFocusedAPP.icon", get_app_icon(activeWindow)) 462 | # 463 | 464 | # if activeWindow != None: 465 | # try: 466 | # activeWindow = os.path.basename(getActiveExecutablePath()) 467 | # except NameError as e: 468 | # print("Name Error: Get Active Window Title") 469 | # 470 | """Checking for Default Input/Output Devices""" 471 | if counter >= 35: 472 | counter = 0 473 | 474 | """Advance Mouse""" 475 | if updateXY: 476 | mp = pyautogui.position() ## Making the call for mouse position once instead of twice.. cause performance :) 477 | TPClient.stateUpdateMany([ 478 | { 479 | "id": f'KillerBOSS.TP.Plugins.AdvanceMouse.MousePos.X', 480 | "value": str(mp[0]) 481 | }, 482 | { 483 | "id": f'KillerBOSS.TP.Plugins.AdvanceMouse.MousePos.Y', 484 | "value": str(mp[1]) 485 | }]) 486 | else: 487 | Timer.cancel() 488 | print('canceled the Timer') 489 | 490 | 491 | ################################################## 492 | #____________________ON START____________________# 493 | audio_exempt_list = [] 494 | running = False 495 | @TPClient.on('info') 496 | def onStart(data): 497 | print(data) 498 | if settings := data.get('settings'): 499 | handleSettings(settings, False) 500 | 501 | # audio_exempt_settings = data['settings']['Audio State Exemption List'] 502 | # global audio_exempt_list 503 | # a_split = audio_exempt_settings.split(",") 504 | # for x in a_split: 505 | # if ".exe" in x: 506 | # audio_exempt_list.append(x) 507 | 508 | """Threading Timebooted Loop""" 509 | th=threading.Thread(target=timebooted_loop, daemon=True) 510 | th.start() 511 | 512 | """Checking if Plugin needs updated""" 513 | try: 514 | github_check = TouchPortalAPI.Tools.updateCheck("KillerBOSS2019", "WinTools") 515 | plugin_version = str(data['pluginVersion']) 516 | plugin_version = plugin_version[:1] + "." + plugin_version[1:] 517 | if github_check[1:4] != plugin_version[0:3]: 518 | TPClient.showNotification( 519 | notificationId="KillerBOSS.TP.Plugins.Update_Check", 520 | title=f"WinTools v{github_check[1:4]} is available", 521 | msg="A new Wintools Version is available and ready to Download. This may include Bug Fixes and or New Features", 522 | options= [{ 523 | "id":"Download Update", 524 | "title":"Click here to Update" 525 | }]) 526 | except: 527 | print("Something went wrong checking update") 528 | pass 529 | 530 | """Updating Monitor/VD's and Audio Details for Choices""" 531 | check_number_of_monitors() 532 | get_default_input_output(powershell=False) 533 | vd_check() 534 | 535 | """ Getting Powerplans and Updating Choice List + Current Power Plan State""" 536 | pplans = get_powerplans() 537 | pplans_list =[] 538 | for item in pplans: 539 | pplans_list.append(item) 540 | TPClient.stateUpdate("KillerBOSS.TP.Plugins.winsettings.powerplan_current", get_powerplans(currentcheck=True)) 541 | TPClient.choiceUpdate("KillerBOSS.TP.Plugins.winsettings.powerplan_choice", pplans_list) ### Updating Power Plan Choices 542 | 543 | 544 | """Updating Choices for Windows Settings options from util.py""" 545 | TPClient.choiceUpdate("KillerBOSS.TP.Plugins.winsettings.choice", activate_windows_setting()) 546 | 547 | """Getting TTS Output Devices and Updating Choices""" 548 | voices = [voice.name for voice in getAllVoices()] 549 | the_devices = getAllOutput_TTS2() 550 | tts_outputs = [] 551 | for item in the_devices: 552 | tts_outputs.append(item) 553 | TPClient.choiceUpdate("KillerBOSS.TP.Plugins.TextToSpeech.output", tts_outputs) 554 | TPClient.choiceUpdate("KillerBOSS.TP.Plugins.TextToSpeech.voices", voices) 555 | 556 | 557 | """Setting Default Audio Slider""" 558 | TPClient.send({ 559 | "type":"connectorUpdate", 560 | "connectorId":"pc_Windows-Tools_KillerBOSS.TP.Plugins.VolumeMixer.connectors.APPcontrol|KillerBOSS.TP.Plugins.VolumeMixer.slidercontrol=Master Volume", 561 | "value": str(getMasterVolume()) 562 | }) 563 | 564 | global running 565 | running = True 566 | updateStates() 567 | run_callback() 568 | 569 | """Starting Clipboard listener from util.py""" 570 | # clip_list_thread = threading.Thread(target=clipboard_listener, daemon=True) 571 | # clip_list_thread.start() 572 | 573 | 574 | def run_callback(): 575 | """This is how we are starting the CallBack, Why? Because it works...""" 576 | try: 577 | MagicManager.magic_session(WinAudioCallBack) 578 | #MagicManager.add_magic_app 579 | except NotImplementedError as err: 580 | print(f"--------- Magic already in session!! ---------\n------{err}------") 581 | 582 | 583 | ### Starting Schedule Thread ### 584 | stop_run_continuously = run_continuously() 585 | """============ SETTINGS ===============""" 586 | audio_exempt_list = [] 587 | settings = {} 588 | def handleSettings(settings, on_connect=False): 589 | newsettings = { list(settings[i])[0] : list(settings[i].values())[0] for i in range(len(settings)) } 590 | global stop_run_continuously 591 | global audio_exempt_list 592 | ###Stopping Scheduled Tasks and Clearing List 593 | stop_run_continuously.set() 594 | schedule.clear() 595 | time.sleep(2) 596 | 597 | """Checking for any Exempt .Exe and building list to avoid making audio states""" 598 | audio_exempt_settings=newsettings['Audio State Exemption List'] 599 | audio_exempt_list = [] 600 | a_split = audio_exempt_settings.split(",") 601 | for x in a_split: 602 | if ".exe" in x: 603 | audio_exempt_list.append(x) 604 | for x in audio_exempt_list: 605 | if x in global_states: 606 | TPClient.removeStateMany([f"KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{x}.muteState", f"KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{x}", f"KillerBOSS.TP.Plugins.VolumeMixer.CreateState.{x}.active"]) 607 | ################################### 608 | 609 | for scheduleFunc in [(disk_usage, "Update Interval: Hard Drive"), 610 | (get_ip_loop, "Update Interval: Public IP"), 611 | (check_number_of_monitors, "Update Interval: Active Monitors"), 612 | (get_windows_update, "Update Interval: Active Windows"), 613 | (vd_check, "Update Interval: Active Virtual Desktops")]: 614 | interval = float(newsettings[scheduleFunc[1]]) 615 | 616 | if int(newsettings[scheduleFunc[1]]) > 0: 617 | schedule.every(interval).seconds.do(scheduleFunc[0]) 618 | print(f"{scheduleFunc[1]} is now {interval}") 619 | else: 620 | print(f"{scheduleFunc[1]} is TURNED OFF") 621 | 622 | 623 | if newsettings['Clipboard Listener (ON / OFF)'] == "ON": 624 | print("WUT WHY") 625 | 626 | try: 627 | clip_list_thread = threading.Thread(target=clipboard_listener, daemon=True) 628 | clip_list_thread.start() 629 | except: 630 | print("Error starting clipboard listener, already exists") 631 | 632 | 633 | """ IF Disk Usage we are Firing it ONE TIME First 634 | So Audio States Don't Mix Later""" 635 | if int(newsettings['Update Interval: Hard Drive']) > 0: 636 | disk_usage() 637 | 638 | 639 | if int(newsettings['Update Interval: Active Virtual Desktops']) >0: 640 | schedule.every(5).seconds.do(current_vd) 641 | 642 | """Scheduling Loop to Get Default Input and Output Devices""" 643 | schedule.every(3).minutes.do(get_default_input_output) 644 | 645 | 646 | 647 | """Starting Schedule Again""" 648 | stop_run_continuously = run_continuously() 649 | 650 | 651 | if newsettings['DEBUG MODE / LOGGING']=="ON": 652 | debug_activate() 653 | """Starting Windows Audio Callback """ 654 | pythoncom.CoInitialize() 655 | return settings 656 | 657 | 658 | @TPClient.on(TouchPortalAPI.TYPES.onNotificationOptionClicked) 659 | def check_noti(data): 660 | print(data) 661 | if data['optionId'] == 'Download Update': 662 | print("ok lets open it") 663 | github_check = TouchPortalAPI.Tools.updateCheck("KillerBOSS2019", "WinTools") 664 | out(f"Start https://github.com/KillerBOSS2019/WinTools/releases/tag/{github_check}") 665 | 666 | """ Settings Handler """ 667 | @TPClient.on(TouchPortalAPI.TYPES.onSettingUpdate) 668 | def onSettingUpdate(data): 669 | if (settings := data.get('values')): 670 | handleSettings(settings, False) 671 | 672 | 673 | 674 | """ Used to assure only one mouse capture runs at a time """ 675 | cap_live = False 676 | """ ACTIONS """ 677 | @TPClient.on(TouchPortalAPI.TYPES.onAction) 678 | def Actions(data): 679 | global TTSThread 680 | print(data) 681 | if data['actionId'] == 'KillerBOSS.TP.Plugins.VolumeMixer.Mute/Unmute': 682 | if data['data'][0]['value'] is not '': 683 | muteAndUnMute(data['data'][0]['value'], data['data'][1]['value']) 684 | if data['actionId'] == 'KillerBOSS.TP.Plugins.VolumeMixer.Increase/DecreaseVolume': 685 | volumeChanger(data['data'][0]['value'], data['data'][1]['value'], data['data'][2]['value']) 686 | 687 | if data['actionId'] == 'KillerBOSS.TP.Plugins.VolumeMixer.SetmasterVolume': 688 | setMasterVolume(data['data'][0]['value']) 689 | 690 | if data['actionId'] == 'KillerBOSS.TP.Plugins.AdvanceMouse.HoldDownToggle': 691 | if data['data'][0]['value'] == 'Down': 692 | pyautogui.mouseDown(button=(data['data'][1]['value']).lower()) 693 | elif data['data'][0]['value'] == "Up": 694 | pyautogui.mouseUp(button=(data['data'][1]['value']).lower()) 695 | if data['actionId'] == "KillerBOSS.TP.Plugins.AdvanceMouse.teleport": 696 | AdvancedMouseFunction(int(data['data'][0]['value']),int(data['data'][1]['value']), int(data['data'][3]['value']), data['data'][2]['value']) 697 | if data['actionId'] == "KillerBOSS.TP.Plugins.AdvanceMouse.MouseClick": 698 | pyautogui.click(clicks=int(data['data'][0]['value']), button=(data['data'][2]['value']).lower(), interval=float(data['data'][1]['value'])) 699 | if data['actionId'] == 'KillerBOSS.TP.Plugins.AdvanceMouse.Function': 700 | try: 701 | pyautogui.move(int(data['data'][0]['value']), int(data['data'][1]['value'])) 702 | except Exception: 703 | pass 704 | if data['actionId'] == 'KillerBOSS.TP.Plugins.ChangeAudioOutput' and data['data'][0]['value'] != "Pick One": 705 | print('powershell is running') 706 | AudioDeviceCmdlets(f"(Get-AudioDevice -list | Where-Object Name -like (\'{data['data'][1]['value']}') | Set-AudioDevice).Name", output=False) 707 | if data['actionId'] == "KillerBOSS.TP.Plugins.AdvanceMouse.StopMouseUpdate": 708 | global updateXY 709 | if data['data'][0]['value'] == "OFF": 710 | updateXY = False 711 | else: 712 | updateXY = True 713 | 714 | ## Screencap Window Current 715 | if data['actionId'] == "KillerBOSS.TP.Plugins.window.current": 716 | if data['data'][0]['value'] == "Clipboard": 717 | current_window = pygetwindow.getActiveWindowTitle() 718 | screenshot_window(capture_type=3, window_title=current_window, clipboard=True) 719 | 720 | elif data['data'][0]['value'] == "File": 721 | current_window = pygetwindow.getActiveWindowTitle() 722 | afile_name = (data['data'][1]['value']) +"/" +(data['data'][2]['value']) 723 | screenshot_window(capture_type=3, window_title=current_window, clipboard=False, save_location=afile_name) 724 | 725 | ##Screen Cap Window Wildcard to FILE 726 | if data['actionId'] == "KillerBOSS.TP.Plugins.screencapture.window.file.wildcard": 727 | global windows_active 728 | windows_active = get_windows() 729 | for thing in windows_active: 730 | if data['data'][0]['value'].lower() in thing.lower(): 731 | print("We found", thing) 732 | if data['data'][4]['value'] == "Clipboard": 733 | screenshot_window(capture_type=int(data['data'][1]['value']), window_title=thing, clipboard=True) 734 | 735 | elif data['data'][4]['value'] == "File": 736 | print("File stuf") 737 | afile_name = (data['data'][2]['value']) +"/" +(data['data'][3]['value']) 738 | screenshot_window(capture_type=int(data['data'][1]['value']), window_title=thing, clipboard=False, save_location=afile_name) 739 | break 740 | 741 | if data['actionId'] == "KillerBOSS.TP.Plugins.screencapture.full.file": 742 | if data['data'][1]['value'] == "Clipboard": 743 | try: 744 | screenshot_monitor(monitor_number=(data['data'][0]['value']), clipboard=True) 745 | except: 746 | pass 747 | elif data['data'][1]['value'] == "File": 748 | try: 749 | afile_name = (data['data'][2]['value']) +"/" +(data['data'][3]['value']) 750 | screenshot_monitor(monitor_number=(data['data'][0]['value']), filename=afile_name, clipboard=False) 751 | except: 752 | pass 753 | 754 | if data['actionId'] == "KillerBOSS.TP.Plugins.screencapture.window.file": 755 | if (data['data'][0]['value']): 756 | if data['data'][4]['value'] == "Clipboard": 757 | screenshot_window(capture_type=int(data['data'][1]['value']), window_title=data['data'][0]['value'], clipboard=True) 758 | if data['data'][4]['value'] == "File": 759 | afile_name = (data['data'][2]['value']) +"/" +(data['data'][3]['value']) 760 | screenshot_window(capture_type=int(data['data'][1]['value']), window_title=data['data'][0]['value'], clipboard=False, save_location=afile_name) 761 | 762 | 763 | if data['actionId'] == "KillerBOSS.TP.Plugins.screencapture.processcheck": 764 | app_to_check = data['data'][0]['value'].lower() 765 | focus = data['data'][1]['value'] 766 | afocus_type = data['data'][2]['value'] 767 | shortcut_to_open = "" 768 | if data['data'][3]['value']: 769 | shortcut_to_open = data['data'][3]['value'] 770 | if focus == "Focus": 771 | focus_check = True 772 | else: 773 | focus_check = False 774 | 775 | check_process(app_to_check, shortcut_to_open, focus=focus_check, focus_type=afocus_type) 776 | 777 | if data['actionId'] == "KillerBOSS.TP.Plugins.capture.clipboard": 778 | send_to_clipboard("text", data['data'][0]['value'] ) 779 | 780 | if data['actionId'] == "KillerBOSS.TP.Plugins.capture.clipboard.toValue": 781 | """Save Clipboard Data to a Custom TP Value""" 782 | TPClient.stateUpdate(stateId=data['data'][0]['value'], stateValue=str(get_clipboard_data())) 783 | 784 | if data['actionId'] == "KillerBOSS.TP.Plugins.virtualdesktop.actions": 785 | choice = data['data'][0]['value'] 786 | virtual_desktop(target_desktop=choice) 787 | 788 | if data['actionId'] == "KillerBOSS.TP.Plugins.winsettings.rotate_display": 789 | if data['data'][0]['value'] != "Pick a Monitor": 790 | rotate_display(int(data['data'][0]['value']), data['data'][1]['value']) 791 | 792 | 793 | if data['actionId'] == "KillerBOSS.TP.Plugins.winsettings.shutdown": 794 | win_shutdown(data['data'][0]['value']) 795 | 796 | if data['actionId'] == "KillerBOSS.TP.Plugins.winsettings.primary_monitor": 797 | change_primary(data['data'][0]['value']) 798 | 799 | 800 | if data['actionId'] == "KillerBOSS.TP.Plugins.winsettings.powerplan": 801 | change_pplan(data['data'][0]['value']) 802 | TPClient.stateUpdate("KillerBOSS.TP.Plugins.winsettings.powerplan_current", get_powerplans(currentcheck=True)) 803 | 804 | 805 | if data['actionId'] == "KillerBOSS.TP.Plugins.winsettings.move_window": 806 | move_win_button(data['data'][0]['value']) 807 | 808 | if data['actionId'] == "KillerBOSS.TP.Plugins.virtualdesktop.actions.move_window": 809 | choice = data['data'][0]['value'] 810 | if data['data'][1]['value'] == "False": 811 | virtual_desktop(move=True, target_desktop=choice) 812 | if data['data'][1]['value'] == "True": 813 | virtual_desktop(move=True, target_desktop=choice, pinned=True) 814 | 815 | if data['actionId'] == 'KillerBOSS.TP.Plugins.virtualdesktop.create': 816 | create_vd(data['data'][0]['value']) 817 | if data['actionId'] == 'KillerBOSS.TP.Plugins.virtualdesktop.remove': 818 | remove_vd(data['data'][0]['value']) 819 | if data['actionId'] == 'KillerBOSS.TP.Plugins.virtualdesktop.rename': 820 | rename_vd(name=data['data'][0]['value'], number=data['data'][1]['value']) 821 | 822 | 823 | if data['actionId'] == "KillerBOSS.TP.Plugins.magnifier.actions": 824 | magnifier(data['data'][0]['value']) 825 | 826 | if data['actionId'] == "KillerBOSS.TP.Plugins.magnifier.onHold.actions": 827 | if data['data'][0]['value'] == "Zoom": 828 | mag_level(int(data['data'][1]['value'])) 829 | 830 | if data['actionId'] == "KillerBOSS.TP.Plugins.toast.create": 831 | win_toast(atitle=data['data'][0]['value'], amsg=data['data'][1]['value'], aduration=data['data'][2]['value'], icon=data['data'][5]['value'], buttonText=data['data'][3]['value'], buttonlink=data['data'][4]['value'], sound=data['data'][6]['value']) 832 | 833 | if data['actionId'] == "KillerBOSS.TP.Plugins.winextra.emojipanel": 834 | winextra("Emoji") 835 | 836 | if data['actionId'] == "KillerBOSS.TP.Plugins.winextra.keyboard": 837 | winextra("Keyboard") 838 | 839 | if data['actionId'] == "KillerBOSS.TP.Plugins.winsettings.action": 840 | activate_windows_setting(data['data'][0]['value']) 841 | 842 | if data['actionId'] == "KillerBOSS.TP.Plugins.TextToSpeech.speak": 843 | TTSThread = threading.Thread(target=TextToSpeech,daemon=True, args=(data['data'][1]['value'], data['data'][0]['value'], int(data['data'][2]['value']), int(data['data'][3]['value']), data['data'][4]['value'])) 844 | TTSThread.start() 845 | 846 | if data['actionId'] == "KillerBOSS.TP.Plugins.TextToSpeech.stop": 847 | if TTSThread.is_alive(): 848 | sd.stop() 849 | pass 850 | 851 | if data['actionId'] == "KillerBOSS.TP.Plugins.winsettings.active.mouseCapture": 852 | if data['data'][0]['value'] =="ON": 853 | global cap_live 854 | if cap_live: 855 | print("DENIED, ONLY ONE ALLOWED") 856 | elif not cap_live: 857 | if data['data'][3]['value'] == "None": 858 | print("NO OVERLAY WANTED") 859 | th1 = threading.Thread(target=turn_on_cap, daemon=True, args=(int(data['data'][1]['value']), int(data['data'][2]['value']), None)) 860 | cap_live = True 861 | th1.start() 862 | 863 | if data['data'][3]['value']: 864 | if ".png" in data['data'][3]['value']: 865 | print("*"*20, "OVERLAY REQUESTED", "*"*20) 866 | path = os.getcwd() 867 | path = path+ f"\mouse_overlays\\" + data['data'][3]['value'] 868 | print(path) 869 | img = Image.open(path) 870 | if img.size[0] == int(data['data'][1]['value']) and img.size[1] == int(data['data'][2]['value']): 871 | print("sized properly") 872 | th1 = threading.Thread(target=turn_on_cap,daemon=True, args=(int(data['data'][1]['value']), int(data['data'][2]['value']), img)) 873 | cap_live = True 874 | th1.start() 875 | 876 | elif img.size[0] != int(data['data'][1]['value']): 877 | print("NOT EQUAL WE AHVE TO RESIZE IT") 878 | print(int(data['data'][1]['value']), int(data['data'][2]['value'])) 879 | resized =resize_image(img, int(data['data'][1]['value']), int(data['data'][2]['value'])) 880 | th1 = threading.Thread(target=turn_on_cap,daemon=True, args=(int(data['data'][1]['value']), int(data['data'][2]['value']), resized)) 881 | cap_live = True 882 | th1.start() 883 | 884 | elif data['data'][0]['value'] == "OFF": 885 | cap_live=False 886 | global if_running 887 | if_running = False 888 | pass 889 | 890 | 891 | def turn_on_cap(height=None, width=None, overlayimage=None): 892 | global cap_live 893 | while cap_live: 894 | img = capture_around_mouse(height, width, livecap=True, overlay=overlayimage) 895 | if img != "NO RESULT": 896 | TPClient.stateUpdate(stateId="KillerBOSS.TP.Plugins.winsettings.active.mouseCapture", stateValue=getFrame_base64(img).decode()) 897 | time.sleep(0.10) 898 | elif img == "NO RESULT": 899 | print("NO RESULT.. STOPPED") 900 | cap_live = False 901 | break 902 | if not cap_live: 903 | print("Live Cap Stopped") 904 | cap_live = False 905 | break 906 | 907 | 908 | 909 | @TPClient.on(TouchPortalAPI.TYPES.onHold_down) 910 | def heldingButton(data): 911 | print(data) 912 | while True: 913 | if TPClient.isActionBeingHeld('KillerBOSS.TP.Plugins.AdvanceMouse.MouseClick'): 914 | pyautogui.click(clicks=int(data['data'][0]['value']), button=(data['data'][2]['value']).lower(), interval=float(data['data'][1]['value'])) 915 | elif TPClient.isActionBeingHeld('KillerBOSS.TP.Plugins.AdvanceMouse.Function'): 916 | try: 917 | pyautogui.move(int(data['data'][0]['value']), int(data['data'][1]['value'])) 918 | except Exception: 919 | pass 920 | elif TPClient.isActionBeingHeld('KillerBOSS.TP.Plugins.VolumeMixer.Increase/DecreaseVolume'): 921 | if data['data'][1]['value'] == "Decrease": 922 | volumeChanger(data['data'][0]['value'], 'Decrease', data['data'][2]['value']) 923 | sleep(0.05) 924 | elif data['data'][1]['value'] == "Increase": 925 | volumeChanger(data['data'][0]['value'], 'Increase', data['data'][2]['value']) 926 | sleep(0.05) 927 | elif TPClient.isActionBeingHeld('KillerBOSS.TP.Plugins.magnifier.onHold.actions'): 928 | if data['data'][0]['value'] == "Lens X": 929 | magnifer_dimensions(x=True, y=None, onhold=int(data['data'][1]['value'])) 930 | sleep(0.05) 931 | if data['data'][0]['value'] == "Lens Y": 932 | print("uh hi?") 933 | magnifer_dimensions(x=False, y=True, onhold=int(data['data'][1]['value'])) 934 | sleep(0.05) 935 | if data['data'][0]['value'] == "Zoom": 936 | mag_level(int(data['data'][1]['value']), onhold=True) 937 | sleep(0.05) 938 | elif TPClient.isActionBeingHeld('KillerBOSS.TP.Plugins.winsettings.active.mouseCapture'): 939 | if not cap_live: 940 | img=capture_around_mouse(int(data['data'][1]['value']),int(data['data'][2]['value'])) 941 | TPClient.stateUpdate(stateId="KillerBOSS.TP.Plugins.winsettings.active.mouseCapture", stateValue=getFrame_base64(img).decode()) 942 | sleep(0.07) 943 | else: 944 | print("Attempted PUSH + HOLD CAP, but Capture is already live") 945 | sleep(0.35) 946 | else: 947 | break 948 | 949 | 950 | """Getting Input and Output Devices and Updating Choices""" 951 | def updateDeviceOutput(options): 952 | output = AudioDeviceCmdlets('Get-AudioDevice -List | ConvertTo-Json') 953 | outPutDevice = [] 954 | inputDevice = [] 955 | for x in output: 956 | if x['Type'] == "Playback": 957 | outPutDevice.append(x['Name']) 958 | elif x['Type'] == "Recording": 959 | inputDevice.append(x['Name']) 960 | 961 | if options == "Output": 962 | TPClient.choiceUpdate('KillerBOSS.TP.Plugins.ChangeAudioOutput.Device', outPutDevice) 963 | print('updating Output', outPutDevice) 964 | elif options == "Input": 965 | TPClient.choiceUpdate('KillerBOSS.TP.Plugins.ChangeAudioOutput.Device', inputDevice) 966 | print('updating input', outPutDevice) 967 | 968 | oldcursors = [] 969 | @TPClient.on(TYPES.onListChange) 970 | def listChangeAction(data): 971 | print(data) 972 | global oldcursors 973 | if data['actionId'] == 'KillerBOSS.TP.Plugins.ChangeAudioOutput': 974 | try: 975 | updateDeviceOutput(data['value']) 976 | except KeyError: 977 | pass 978 | if data['actionId'] == 'KillerBOSS.TP.Plugins.virtualdesktop.actions.move_window': 979 | vd_check() 980 | 981 | if data['actionId'] == 'KillerBOSS.TP.Plugins.winsettings.active.mouseCapture': 982 | thecursors = get_cursor_choices() 983 | thecursors.append("None") 984 | thecursors.append("LOAD MORE") 985 | if oldcursors != thecursors: 986 | print("not the same mmmk") 987 | TPClient.choiceUpdate("KillerBOSS.TP.Plugins.winsettings.active.mouseCapture.overlay_file", thecursors) 988 | oldcursors = thecursors 989 | 990 | 991 | @TPClient.on(TYPES.onConnectorChange) 992 | def connectors(data): 993 | print(data) 994 | if data['connectorId'] == "KillerBOSS.TP.Plugins.VolumeMixer.connectors.APPcontrol": 995 | if data['data'][0]['value'] == "Master Volume" : 996 | setMasterVolume(data['value']) 997 | elif data['data'][0]['value'] == "Current app": 998 | activeWindow = getActiveExecutablePath() 999 | # print(activeWindow) 1000 | if activeWindow != "": 1001 | volumeChanger(os.path.basename(activeWindow), "Set", data['value']) 1002 | else: 1003 | try: 1004 | volumeChanger(data['data'][0]['value'], "Set", data['value']) 1005 | except: 1006 | pass 1007 | 1008 | if data['connectorId'] == "KillerBOSS.TP.Plugins.Magnifier.connectors.ZoomControl": 1009 | if data['data'][0]['value'] == "Zoom" : 1010 | mag_level(data['value']*16) 1011 | 1012 | if data['data'][0]['value'] == "Lens X" : 1013 | magnifer_dimensions(x=data['value']) 1014 | 1015 | if data['data'][0]['value'] == "Lens Y" : 1016 | magnifer_dimensions(y=data['value']) 1017 | 1018 | 1019 | 1020 | @TPClient.on('closePlugin') 1021 | def Shutdown(data): 1022 | global stop_run_continuously 1023 | global running, Timer 1024 | running = False 1025 | schedule.clear() 1026 | Timer.cancel() 1027 | TPClient.disconnect() 1028 | sys.exit() 1029 | 1030 | 1031 | 1032 | TPClient.connect() 1033 | 1034 | -------------------------------------------------------------------------------- /src/requirements.txt: -------------------------------------------------------------------------------- 1 | altgraph==0.17.2 2 | audio2numpy==0.1.2 3 | certifi==2021.10.8 4 | cffi==1.15.0 5 | charset-normalizer==2.0.9 6 | comtypes==1.1.10 7 | ffmpeg==1.4 8 | future==0.18.2 9 | idna==3.3 10 | MouseInfo==0.1.3 11 | mss==6.1.0 12 | numpy==1.22.1 13 | pefile==2021.9.3 14 | Pillow==9.0.0 15 | psutil==5.9.0 16 | PyAutoGUI==0.9.53 17 | https://github.com/AndreMiras/pycaw/archive/refs/tags/v20190904.zip 18 | pycparser==2.21 19 | pyee==8.2.2 20 | PyGetWindow==0.0.9 21 | PyGetWindowMP @ https://github.com/Kalmat/PyGetWindow/archive/refs/heads/master.zip 22 | pyinstaller==4.7 23 | pyinstaller-hooks-contrib==2021.4 24 | PyMsgBox==1.0.9 25 | pyperclip==1.8.2 26 | pyping==0.0.6 27 | pypiwin32==223 28 | PyRect==0.1.4 29 | PyScreeze==0.1.28 30 | python-dateutil==2.8.2 31 | pyttsx3==2.90 32 | pytweening==1.0.4 33 | pyvda==0.2.4 34 | pywin32==302 35 | pywin32-ctypes==0.2.0 36 | requests==2.27.0 37 | schedule==1.1.0 38 | scipy==1.7.3 39 | screeninfo==0.8 40 | six==1.16.0 41 | sounddevice==0.4.4 42 | TouchPortal-API==1.6 43 | urllib3==1.26.7 44 | winotify==1.1.0 45 | wintoast==0.2 46 | --------------------------------------------------------------------------------