Sound Mixer - скрипт, благодаря которому вы сможете создавать бинды на изменение звука в любых запущенных приложениях вашего ПК.
Актуальная версия - 0.6 Release
Звуковой микшер - используйте интуитивно понятный пользовательский интерфейс для создания/настройки профильных горячих клавиш.
Функции сортировки процессов и изменения звука в активном окне позволят без лишних заморочек
найти, задать и сохранить.
Удобно ли при первой необходимости убрать звук в активном окне, увеличить звучание беседы "дискорда" и слегка добавить громкости к играющей музыке в браузере?
Решать только вам.
/// Source 0.4v \\\
AutoHotKey:
; author - bass_devware
; If you copy, modify or use my script lines for your own goals - indicate my authorship.
; @bass_devware
#SingleInstance ignore
OnExit, ExitLabel
if not A_IsAdmin
Run *RunAs "%A_ScriptFullPath%",,UseErrorLevel
if errorlevel
{
MsgBox, 262160, SoundMixer Reborn, For the script to work properly`, you must run it with admin rights.
ExitApp
}
clientv = 4
;/////Проверка обновления \\\\\
oWhr := ComObjCreate("WinHttp.WinHttpRequest.5.1")
oWhr.Open("GET", "https://raw.githubusercontent.com/MirchikAhtung/soundmixer/master/readme.txt", false)
oWhr.Send()
html := oWhr.ResponseText
RegExMatch(html, "0.(.*)v`n`n 2.", version)
if version1 != % clientv
{
MsgBox, 262212, Update released, Version of your client - 0.%clientv%`nLatest version - 0.%version1%`n`nWant to download the new version now?`n`n"YES" - Open Browser Page`n"NO" - Open current version (0.%clientv%)
IfMsgBox Yes
{
run, https://github.com/MirchikAhtung/soundmixer/blob/master/SoundMixer_R0.%version1%.exe
ExitApp
}
}
;/////Проверка обновления \\\\\
var = 0
Gui, Margin, 10, 10
Gui, Add, ListView, w500 h600 vList +disabled +AltSubmit, PID|Process Name|Command Line
for process in ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process")
LV_Add("", process.ProcessID, process.Name, process.CommandLine)
LV_ModifyCol()
Gui, Add, Edit, x16 y650 w220 h20 vEdit +disabled,
Gui, Add, Hotkey, x16 y625 w60 h20 gAWHotkey vAWHotkey +disabled,
Gui, Add, Radio, x16 y675 w70 h20 vSelected gSelected +disabled, Selected
Gui, Add, Radio, x85 y675 w100 h20 vAW gAW +disabled, Active Window
Gui, Add, Button, x246 y625 w80 h20 +Disabled vEdit2 gEdit, Edit
Gui, Add, Button, x246 y650 w80 h20 vAddBtn gAddBtn, Add
Gui, Add, Button, x186 y675 w50 h20 vrefreshprofiles grefreshprofiles , Refresh
Gui, Add, Button, x246 y675 w80 h20 +disabled vRemove gRemove, Remove
Gui, Add, GroupBox, x6 y610 w330 h95 ,
Gui, Add, GroupBox, x346 y610 w160 h95 ,
Gui, Add, DropDownList, x86 y625 w150 h20 R5 vDDsL hwndhDDL gDDL ,
Gui, Add, Radio, x352 y657 w75 w73 vAP gAllProcess +Checked, All process
Gui, Add, Radio, x430 y657 w80 w73 vOM gOnlyMedia, Only media
Gui, Add, Slider, x350 y680 w152 h20 vSlider Range0-100 ToolTip +disabled, 0
Gui, Add, Button, x356 y625 w70 h20 vSave gSave +disabled, Save
Gui, Add, Button, x430 y625 w70 h20 vCancel gCancel +disabled, Cancel
Gui, Show,w510 h710, SoundMixer Reborn | @bass_devware | 0.%clientv%v
return
AllProcess:
LV_Delete()
for process in ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process")
LV_Add("", process.ProcessID, process.Name, process.CommandLine)
LV_ModifyCol()
return
OnlyMedia:
LV_Delete()
Loop, Parse, % GetActive_Media(), `,
{
PATH := GetModuleFileNameEx(A_LoopField)
Loop, % PATH
Name := A_LoopFileName
LV_Add("", A_LoopField, Name, Path)
}
LV_ModifyCol()
return
AddBtn:
GuiControl,enable,List
GuiControl, disable, refreshprofiles
add = 1
return
GuiContextMenu:
selectedis = %A_EventInfo%
if A_EventInfo != 0
{
GuiControl, disable, AP
GuiControl,disable,OM
GuiControl, disable, DDsL
GuiControl,disable,List
GuiControl,disable,AddBtn
GuiControl,enable,cancel
GuiControl,enable,Selected
GuiControl,enable,AW
LV_GetText(selectedprocessPID, selectedis, 1)
LV_GetText(selectedprocessName, selectedis, 2)
gui, submit, nohide
GuiControl,,edit, PID - %selectedprocessPID% | Process - %selectedprocessName%
}
return
AWHotkey:
if editvar != save
{
GuiControl,enable,save
GuiControl,enable,slider
}
return
Selected:
GuiControl,enable,AWHotkey
tosave = 1
return
AW:
GuiControl,enable,AWHotkey
tosave = 2
return
Save:
if tosave = 2
{
selectedprocessPID = ActiveWindow
selectedprocessName = ActiveWindow
}
if AWHotkey !=
{
GuiControl, Enable, refreshprofiles
GuiControl,disable,AWHotkey
gui, submit, nohide
ItemText = %slider% | %AWHotkey% | %selectedprocessPID% | %selectedprocessName%
SendMessage, 0x143, 0, &ItemText , , ahk_id %hDDL% ; CB_ADDSTRING
GuiControl,enable,DDsL
GuiControl,disable,Selected
GuiControl,disable,AW
GuiControl,disable,save
GuiControl,disable, slider
GuiControl,Enable,AddBtn
GuiControl,disable,cancel
GuiControl,,AWHotkey,
GuiControl, Enable, AP
GuiControl,Enable,OM
LV_Modify(selectedis, "-Focus")
goto refreshprofiles
}
return
Cancel:
GuiControl,enable,DDsL
GuiControl,disable,Selected
GuiControl,disable,AW
GuiControl,disable,save
GuiControl,Enable,AddBtn
GuiControl,disable,cancel
GuiControl,,AWHotkey,
GuiControl,disable,AWHotkey
GuiControl,disable,slider
GuiControl,Enable,AP
GuiControl,Enable,OM
LV_Modify(selectedis, "-Focus")
return
remove:
gui, submit, nohide
RegExMatch(DDsL, "(.*) \Q|\E (.*) \Q|\E (.*) \Q|\E (.*)", rprofile)
hotkey, %rprofile2%, hotkey, off, UseErrorLevel
SendMessage, 0x158, 1, &DDsL, , ahk_id %hDDL% ; CB_FINDSTRINGEXACT
ItemIndex := ErrorLevel
SendMessage, 0x0144, ItemIndex, , , ahk_id %hDDL% ; CB_DELETESTRING
SendMessage, 0x014F, 1, , , ahk_id %hDDL% ; CB_SHOWDROPDOWN
GuiControl,disable,remove
GuiControl,disable,edit2
return
DDL:
gui, submit, nohide
if DDsL !=
{
GuiControl,enable,remove
GuiControl,enable,edit2
}
return
edit:
gui, submit, nohide
if editvar != save
{
RegExMatch(DDsL, "(.*)\Q|\E(.*)\Q|\E(.*)\Q|\E(.*)", profile)
GuiControl,enable,slider
GuiControl,enable,AWHotkey
GuiControl,disable,list
GuiControl,disable,remove
GuiControl,disable,AddBtn
GuiControl,, edit2, Save
GuiControl, Disable, refreshprofiles
editvar = save
}
else
{
if AWHotkey =
{
AWHotkey := profile2
}
GuiControl,Disable,AWHotkey
upd = %slider%|%AWHotkey%|%profile3%|%profile4%
ItemText := DDsL
Sleep 100
SendMessage, 0x158, 1, &ItemText, , ahk_id %hDDL% ; CB_FINDSTRINGEXACT
ItemIndex := ErrorLevel
SendMessage, 0x0144, ItemIndex, , , ahk_id %hDDL% ; CB_DELETESTRING
GuiControl,disable,slider
ItemText := upd
SendMessage, 0x014A, ItemIndex, &ItemText , , ahk_id %hDDL% ; CB_INSERTSTRING
GuiControl,, edit2, Edit
GuiControl,disable,edit2
GuiControl,Enable,AddBtn
editvar = 0
SendMessage, 0x014F, 1, , , ahk_id %hDDL% ; CB_SHOWDROPDOWN
}
return
refreshprofiles:
ControlGet, refprofiles, List,, ComboBox1, A
Loop, parse, refprofiles, `n, `r
{
RegExMatch(A_LoopField, "(.*) \Q|\E (.*) \Q|\E (.*) \Q|\E (.*)", profile%A_Index%)
If (profile%A_Index%1 = "" Or profile%A_Index%2 = "" Or profile%A_Index%3 = "" Or profile%A_Index%4 = "")
{
MsgBox Файл с профилями повреждён. [ №%A_Index% ]
return
}
tempvar := profile%A_Index%2
pid%tempvar% := profile%A_Index%3
process%tempvar% := profile%A_Index%4
%tempvar% := profile%A_Index%1
hotkey, %tempvar%, hotkey, on, UseErrorLevel
}
return
hotkey:
If (pid%A_ThisHotkey% = "ActiveWindow" Or process%A_ThisHotkey% = "ActiveWindow")
{
WinGet, pid%A_ThisHotkey%, PID, A
}
SetAppVolume(pid%A_ThisHotkey%, %A_ThisHotkey%)
return
ExitLabel:
if A_ExitReason not in Logoff,Shutdown ; Не ставьте пробелы до и после запятой.
{
MsgBox, 262180, SoundMixerR | Exit, Are you sure you want to quit?
IfMsgBox, No
return
}
ExitApp
return
SetAppVolume(pid, MasterVolume)
{
IMMDeviceEnumerator := ComObjCreate("{BCDE0395-E52F-467C-8E3D-C4579291692E}", "{A95664D2-9614-4F35-A746-DE8DB63617E6}")
DllCall(NumGet(NumGet(IMMDeviceEnumerator+0)+4*A_PtrSize), "UPtr", IMMDeviceEnumerator, "UInt", 0, "UInt", 1, "UPtrP", IMMDevice, "UInt")
ObjRelease(IMMDeviceEnumerator)
VarSetCapacity(GUID, 16)
DllCall("Ole32.dll\CLSIDFromString", "Str", "{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}", "UPtr", &GUID)
DllCall(NumGet(NumGet(IMMDevice+0)+3*A_PtrSize), "UPtr", IMMDevice, "UPtr", &GUID, "UInt", 23, "UPtr", 0, "UPtrP", IAudioSessionManager2, "UInt")
ObjRelease(IMMDevice)
DllCall(NumGet(NumGet(IAudioSessionManager2+0)+5*A_PtrSize), "UPtr", IAudioSessionManager2, "UPtrP", IAudioSessionEnumerator, "UInt")
ObjRelease(IAudioSessionManager2)
DllCall(NumGet(NumGet(IAudioSessionEnumerator+0)+3*A_PtrSize), "UPtr", IAudioSessionEnumerator, "UIntP", SessionCount, "UInt")
Loop % SessionCount
{
DllCall(NumGet(NumGet(IAudioSessionEnumerator+0)+4*A_PtrSize), "UPtr", IAudioSessionEnumerator, "Int", A_Index-1, "UPtrP", IAudioSessionControl, "UInt")
IAudioSessionControl2 := ComObjQuery(IAudioSessionControl, "{BFB7FF88-7239-4FC9-8FA2-07C950BE9C6D}")
ObjRelease(IAudioSessionControl)
DllCall(NumGet(NumGet(IAudioSessionControl2+0)+14*A_PtrSize), "UPtr", IAudioSessionControl2, "UIntP", ProcessId, "UInt")
If (pid == ProcessId)
{
ISimpleAudioVolume := ComObjQuery(IAudioSessionControl2, "{87CE5498-68D6-44E5-9215-6DA47EF883D8}")
DllCall(NumGet(NumGet(ISimpleAudioVolume+0)+3*A_PtrSize), "UPtr", ISimpleAudioVolume, "Float", MasterVolume/100.0, "UPtr", 0, "UInt")
ObjRelease(ISimpleAudioVolume)
}
ObjRelease(IAudioSessionControl2)
}
ObjRelease(IAudioSessionEnumerator)
}
GetModuleFileNameEx(p_pid)
{
if A_OSVersion in WIN_95,WIN_98,WIN_ME
{
MsgBox, This Windows version (%A_OSVersion%) is not supported.
return
}
h_process := DllCall( "OpenProcess", "uint", 0x10|0x400, "int", false, "uint", p_pid )
if ( ErrorLevel or h_process = 0 )
return
name_size = 255
VarSetCapacity( name, name_size )
result := DllCall( "psapi.dll\GetModuleFileNameEx" ( A_IsUnicode ? "W" : "A" ), "uint", h_process, "uint", 0, "str", name, "uint", name_size )
DllCall( "CloseHandle", h_process )
return, name
}
GetActive_Media()
{
IMMDeviceEnumerator := ComObjCreate("{BCDE0395-E52F-467C-8E3D-C4579291692E}", "{A95664D2-9614-4F35-A746-DE8DB63617E6}")
DllCall(NumGet(NumGet(IMMDeviceEnumerator+0)+4*A_PtrSize), "UPtr", IMMDeviceEnumerator, "UInt", 0, "UInt", 1, "UPtrP", IMMDevice, "UInt")
ObjRelease(IMMDeviceEnumerator)
VarSetCapacity(GUID, 16)
DllCall("Ole32.dll\CLSIDFromString", "Str", "{77AA99A0-1BD6-484F-8BC7-2C654C9A9B6F}", "UPtr", &GUID)
DllCall(NumGet(NumGet(IMMDevice+0)+3*A_PtrSize), "UPtr", IMMDevice, "UPtr", &GUID, "UInt", 23, "UPtr", 0, "UPtrP", IAudioSessionManager2, "UInt")
ObjRelease(IMMDevice)
DllCall(NumGet(NumGet(IAudioSessionManager2+0)+5*A_PtrSize), "UPtr", IAudioSessionManager2, "UPtrP", IAudioSessionEnumerator, "UInt")
ObjRelease(IAudioSessionManager2)
DllCall(NumGet(NumGet(IAudioSessionEnumerator+0)+3*A_PtrSize), "UPtr", IAudioSessionEnumerator, "UIntP", SessionCount, "UInt")
Loop % SessionCount
{
DllCall(NumGet(NumGet(IAudioSessionEnumerator+0)+4*A_PtrSize), "UPtr", IAudioSessionEnumerator, "Int", A_Index-1, "UPtrP", IAudioSessionControl, "UInt")
IAudioSessionControl2 := ComObjQuery(IAudioSessionControl, "{BFB7FF88-7239-4FC9-8FA2-07C950BE9C6D}")
ObjRelease(IAudioSessionControl)
DllCall(NumGet(NumGet(IAudioSessionControl2+0)+14*A_PtrSize), "UPtr", IAudioSessionControl2, "UIntP", ProcessId, "UInt")
if (ProcessId)
PID .= ProcessId ","
ObjRelease(IAudioSessionControl2)
}
ObjRelease(IAudioSessionEnumerator)
StringTrimRight, PID, PID, 1
return PID
}
end::reload
!end::ExitApp
Lua:
^^^
23.02.2019 - v0.1 /
Выход в свет
---
25.02.2019 - v0.2 /
Авто-обновление
Разделение процессов на all/only multimedia
---
26.02.2019 - v0.3 /
Фикс "мёртвых" кнопок + оптимизация кода
Выключение звука в активном окне
---
05.03.2019 - v0.4 / Reborn
Переработана система профилей
---
12.03.2019 - v0.5 / Reborn
Добавлена возможность выгрузки настроек ваших профилей
Фикс бага с не разворачиваемым окном
---
23.03.2019 - v0.6 / Release
Фикс дублирующихся процессов
Фикс разворачивания окна
При загрузке профиля, PID будет определятся исходя из имени процесса приложения, а не использоваться с указанного .ini файла.
Теперь имеет смысл на постоянной основе пользоваться загрузкой/выгрузкой профиля.
^^^
- Научить скрипт определять процесс нужного окна с играющим мультимедиа.
- [Реализовано] 0.2v
- Добавить возможность создавать неограниченное кол-во хоткеев.
- [Реализовано] 0.4v
- Выключение звука в активном окне
- [Реализовано] 0.3v
- Авто-обновление
- [Реализовано] 0.2v
- Изменение звука по имени процесса
- [Реализовано] 0.6v
- Сохранение настроек
- [Реализовано] 0.5v
- Исправить появляющиеся дубликаты процессов
- [Реализовано] 0.6v
Скачать:
GitHub
В связи с "проблемами" в авто-обновлении скрипта с использованием ресурса blasthack,
мною было принято решение перенести не только проверку AutoUPD на GitHub, но и скачиваемые ресурсы так же.
Вследствие этого - все вложения с файлами (скачивание которых в сумме переваливает 150>) удалены.
Выходящие обновления будут оглашаться в этой теме и поддержка скрипта (по крайне мере до выхода в релиз) прекращена не будет.
Связь/сотрудничество: VK
Отдельная благодарность этому человеку
Последнее редактирование: