player2_dz

The Ultimate Audio Playback Device Switching Script (AHK)

Aug 13th, 2017
630
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ; Script by [email protected] / p2codes
  2. #Persistent         ; This keeps the script running permanently.
  3. #SingleInstance     ; Only allows one instance of the script to run.
  4.  
  5. ; ===============================================================================================
  6. ; Global Variables
  7. ; ===============================================================================================
  8. global curText          := "Output 404"     ; Text on GUI (Updated later)
  9. global selectionIndex   := 1                ; Currently selected output device
  10. global arrNames         := Object()         ; Output devices data (device names)
  11.  
  12. ; Registry Keys & Values used in x64 Win 10 (WARNING: MAY DIFFER ON OTHER VERSIONS OF WINDOWS)
  13. ; ===============================================================================================
  14. ; This is the value that contains the user customisable name (eg Headphones or TV) of the playback device
  15. ; The root path to the audio devices section of the registry
  16. global rootPath = % "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Render"
  17. ; This value is found in %rootPath%\%deviceSubKey%\Properties, and always has this same name across devices
  18. global nameValue = % "{a45c254e-df1c-4efd-8020-67d146a850e0},2"
  19.  
  20. ; ===============================================================================================
  21. ; Script Start-up Instructions                 (Note: This must run before to the hotkey section)
  22. ; ===============================================================================================
  23. createGui()     ; Create GUI (but hidden) so it is ready for use (showing)
  24.  
  25. ; ===============================================================================================
  26. ; Windows HotKey (Win + K by default)
  27. ; ===============================================================================================
  28. #k::
  29. {
  30.     currentEnabledDeviceIndex = % getDeviceInfo()               ; Get device data from registry
  31.     devName = % getNextSelectionName(currentEnabledDeviceIndex) ; Get name of next device to use
  32.     Run nircmd setdefaultsounddevice "%devName%" 1              ; Use name & nircmd to set default playback device
  33.     Run nircmd setdefaultsounddevice "%devName%" 2              ; Use name & nircmd to set default communication device
  34.     showGui(devName)                                            ; Unhide the GUI with text to match device name
  35.     Return                                                      ; Finished
  36. }
  37.  
  38. ; ===============================================================================================
  39. ; Script Functions
  40. ; ===============================================================================================
  41.  
  42. ; Function:     createGui  
  43. ; Description:  Creates a small hidden GUI, named soundToggleWin, suitable for re-use and
  44. ; modification of it's text property, called curText.
  45. ; ===============================================================================================
  46. createGui()
  47. {
  48.     Gui, soundToggleWin:destroy                                         ; Destroy Any Existing Window with name soundToggleWin
  49.     Gui, soundToggleWin: New, -Caption +AlwaysOnTop -SysMenu -Theme     ; Create new UI with name soundToggleWin and set appearance propertiess
  50.     Gui, soundToggleWin: Add, text, x15 y8 vcurText, OutputSample       ; Add text property to UI, named curText, and place it appropriately
  51.     Return                                                              ; Exit
  52. }
  53.  
  54. ; Function:     showGui
  55. ; Description:  Applies properties to and shows the soundToggleWin GUI element,
  56. ; the properties being it's appearance and the text (curText)
  57. ; Input Data:   The text to apply to the GUI's curText text element
  58. ; ===============================================================================================
  59. showGui(guiText)
  60. {
  61.     SysGet, screenx, 0                                                              ; Get ScreenX & Y position values
  62.     SysGet, screeny, 1                                                              ; Same as above
  63.     xpos:=screenx-150                                                               ; Set-up location to place window using screenX/Y values
  64.     ypos:=screeny-62                                                                ; Same as above
  65.     GuiControl, soundToggleWin:, curText, %guiText%                                 ; Set curText text objects text to the input text
  66.     Gui, soundToggleWin:Show, NoActivate x%xpos% y%ypos% h30 w150, soundToggleWin   ; Show the UI with specified size and location
  67.     SetTimer, hideGui, 2000                                                         ; Set timer to run hideGui function in 2000ms (2seconds)
  68.     Return                                                                          ; Exit
  69. }
  70.  
  71. ; Function:     hideGui
  72. ; Description:  Hides the soundToggleWin GUI and disables / deletes the hideGui timer
  73. ; ===============================================================================================
  74. hideGui()
  75. {
  76.     SetTimer, hideGui, Delete   ; Disable & Delete the timer we started
  77.     Gui, soundToggleWin:hide    ; Hide the GUI window
  78.     Return                      ; Exit
  79. }
  80.  
  81. ; Function:     getDeviceInfo  
  82. ; Description:  Retrieves registry data about all output devices that are enabled as a device,
  83. ; in 'Playback Devices', and retrieves which device is the current default output device. It
  84. ; places this data in the arrNames object/array.
  85. ; Return Data:  The Index of the current default playback device relative to the arrNames array
  86. ; ===============================================================================================
  87. getDeviceInfo()
  88. {
  89.     arrNames := Object() ; Empty array of device names 
  90.     largestValue = 0     ; Used to compare device status codes (level:0 values)
  91.  
  92.     ; Loop through all keys in the root path
  93.     Loop, Reg, %rootPath%, K
  94.     {
  95.         curKeyPath = %rootPath%\%a_LoopRegName%                 ; Save current audio devices key path to re-use
  96.         RegRead, deviceStateValue, %curKeyPath%, DeviceState    ; Read device state (enabled/disabled in playback devices)
  97.        
  98.         ; If device is useable as a playback device (enabled)
  99.         if (deviceStateValue = 1) {
  100.            
  101.             RegRead, deviceName, %curKeyPath%\Properties, %nameValue% ; Read device name (user customisable in playback devices)
  102.             arrNames.Insert(deviceName)                               ; Insert device name into array
  103.             deviceStatusCode = % readRegQW(curKeyPath,"Level:0")      ; Get hex code that determines if the device is the current playback device
  104.    
  105.             ; Check which device is the current playback device using hex code retrieved
  106.             ; Currently enabled device has largest hex code value for key "Level:0"
  107.             if (deviceStatusCode > largestValue) {
  108.                 largestValue := deviceStatusCode            ; Update largest value for next iteration
  109.                 currentDeviceIndex := arrNames.MaxIndex()   ; Store index of currently used device so we can avoid it during selection
  110.             }
  111.         }
  112.     }
  113.  
  114.     Return currentDeviceIndex ; Return the default playback device index (index is for the arrNames array)
  115. }
  116.  
  117. ; Function:     getNextSelectionName   
  118. ; Description:  Uses the retrieved default playback device index from getDeviceInfo and the
  119. ; global selectionIndex value to select the next default playback device without conflict and
  120. ; in a sequential manor.
  121. ; Input Data:   The index (reletive to arrNames) of the current default playback device
  122. ; Return Data:  The device name of the next audio device to set as the default playback device
  123. ; ===============================================================================================
  124. getNextSelectionName(deviceIndex)
  125. {
  126.     ; If selected device is the one already enabled, then skip to next device selection
  127.     if (deviceIndex = selectionIndex) {
  128.  
  129.         ; If we reach the max index, reset to 1, otherwise add 1 to move on to the next selection
  130.         if (selectionIndex < arrNames.MaxIndex()) {
  131.             selectionIndex := selectionIndex + 1
  132.         } else {
  133.             selectionIndex = 1
  134.         }
  135.     }
  136.    
  137.     deviceName := arrNames[selectionIndex] ; Store the device name
  138.     Return deviceName   ; Return the device name for the next playback device to use
  139. }
  140.  
  141. ; Function:     readRegQW  
  142. ; Description:  Uses given key & value input to read REG_QWORD values from registry via shell
  143. ; Input Data:   Key - The reg key to search in, Value - The reg value to retrieve the data of
  144. ; Return Data:  The data retrieved from the registry query
  145. ; ===============================================================================================
  146. readRegQW(Key,Value)
  147. {
  148.     shellObj := ComObjCreate("WScript.Shell")   ; Create shell object to use
  149.     ; Use shell object to run CMD with flag /q for quiet mode, /c to run a command
  150.     ; We're using it to query the specified key and retrieve all data
  151.     shellExec := shellObj.Exec("cmd.exe /q /c reg query " Key " /v " Value)
  152.     shellOut := ""                                          ; Set the shellOut variable to empty
  153.     while, !shellExec.StdOut.AtEndOfStream                  ; While the shell hasn't finished outputting
  154.         shellOut := shellExec.StdOut.ReadAll()                  ; Keep reading the shells contents into shellOut
  155.     StringReplace, shellOut, shellOut, REG_QWORD, FINDMENOW ; Replace "REG_QWORD" with "FINDMENOW" (Console text length may vary user to user, this garantuees a position)
  156.     StringGetPos, findPos, shellOut, FINDMENOW              ; Get position of FINDMENOW in string
  157.     shellOut := SubStr(shellOut, findPos+14)                ; Use position of FINDMENOW to cut the string down into just the data we need
  158.     shellOut := RTrim(shellOut,"`n`r ")                     ; Trim off the excess whitespace (newlines) on the right hand side
  159.     shellOut := shellOut + 0                                ; Convert to decimal by adding 0
  160.     return shellOut                                         ; Return decimal registry data
  161. }
Advertisement
Add Comment
Please, Sign In to add comment