 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
codex
Joined: 27 Aug 2009 Posts: 8 Location: Kiev, Ukraine
|
Posted: Thu Aug 27, 2009 1:12 pm Post subject: |
|
|
Thank you for help!
As I said I tried it from VA_SetMute(false, 1) to VA_SetMute(false, 10) - doesn't work at all.
New test script now quits at
Because VA_GetMute(subunit, "device_name") always returns Null...
This code:
| Code: | ^k::
COM_Init()
dev := VA_GetDevice("playback")
MsgBox % VA_GetDeviceName(dev)
if dev
COM_Release(dev)
return |
Shows message box: "Speakers (Realtek Hidh Definition Audio)"
VA_SetMasterMute() works just well so COM_Init is not cause ?
I don't have actual code. What I need is just a right line with VA_SetMute to mute/unmute Mic playback.
So whole code may look like that:
^m::
COM_Init()
VA_SetMute(!VA_GetMute(7),7)
return |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 4471 Location: Qld, Australia
|
Posted: Thu Aug 27, 2009 2:19 pm Post subject: |
|
|
I've uploaded a "verbose" version of my previous script to help us get to the bottom of this. It copies its results to the clipboard and shows a msgbox:
http://www.autohotkey.net/paste/1bc4a7b |
|
| Back to top |
|
 |
codex
Joined: 27 Aug 2009 Posts: 8 Location: Kiev, Ukraine
|
Posted: Thu Aug 27, 2009 2:24 pm Post subject: |
|
|
Thanks! Here is output:
| Code: | > Master Mute
> Speakers
no interface
> Sum
no interface
> Mute
> CD Audio
no interface
> Mute
> Rear Green In
no interface
> Mute
> Rear Black In
no interface
> Mute
> Rear Orange In
no interface
> Mute
> Rear Grey In
no interface
> Mute
> Rear Pink In
no interface
> Mute
> Front Pink In
no interface
> Mute
> Rear Blue In
no interface
> Mute
> Front Green In
no interface
> Side
no interface
> Center
no interface
> Subwoofer
no interface
> Rear
no interface
> Front
no interface
Subunit not found: 1
Device not found: playback:2 |
|
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 4471 Location: Qld, Australia
|
Posted: Thu Aug 27, 2009 2:49 pm Post subject: |
|
|
Do you have data execution prevention enabled for AutoHotkey.exe? VA.ahk uses RegisterCallback, which generates a machine code function to allow native code to call script functions. Data execution prevents these functions from being called, since they are in read/write (not executable) memory.
Actually, VA.ahk only used them to dynamically call a script function. Since that code was written, direct support for dynamic function calls has been added to the language. I've updated VA.ahk to use these instead of RegisterCallback.
If this solves your issue, I'd be curious to know what ErrorLevel is set to in this case:
| Code: | DllCall(cb := RegisterCallback("F"))
MsgBox ErrorLevel: %ErrorLevel%
DllCall("GlobalFree", "uint", cb)
F(){
MsgBox Called F.
} | "Called F" should only appear if DEP is disabled. |
|
| Back to top |
|
 |
codex
Joined: 27 Aug 2009 Posts: 8 Location: Kiev, Ukraine
|
Posted: Thu Aug 27, 2009 2:59 pm Post subject: |
|
|
You right. I added autohotkey.exe to DEP exceptions and VA_SetMute() works now on my system!
If DEP is enabled, errorlevel is 5 (Access Denied ?).
I think some message should be added to VA.ahk to display a warning about DEP
Thank you alot ! |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 4471 Location: Qld, Australia
|
Posted: Thu Aug 27, 2009 3:15 pm Post subject: |
|
|
I suppose you missed the part of my previous post where I said I've updated VA.ahk. It no longer uses RegisterCallback and therefore should not conflict with DEP.
| Quote: | | If DEP is enabled, errorlevel is 5 (Access Denied ?). | Thanks. If I'd thought to suggest DebugBIF, it would've saved us a lot of time; i.e. as soon as VA.ahk fails to call the callback, DebugBIF pops up. |
|
| Back to top |
|
 |
codex
Joined: 27 Aug 2009 Posts: 8 Location: Kiev, Ukraine
|
Posted: Thu Aug 27, 2009 3:21 pm Post subject: |
|
|
| Oh sorry I really missed that. And thanks again ! |
|
| Back to top |
|
 |
codex
Joined: 27 Aug 2009 Posts: 8 Location: Kiev, Ukraine
|
Posted: Thu Aug 27, 2009 4:57 pm Post subject: |
|
|
BTW is it possible to add a wrapper for ISimpleAudioVolume::SetMasterVolume to control session volume ?
Something like VA_SetSessionMasterVolume(level,title) ? |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 4471 Location: Qld, Australia
|
Posted: Fri Aug 28, 2009 1:46 am Post subject: |
|
|
| I've looked into controlling sessions of other applications, but it doesn't seem to be allowed. |
|
| Back to top |
|
 |
codex
Joined: 27 Aug 2009 Posts: 8 Location: Kiev, Ukraine
|
Posted: Fri Aug 28, 2009 7:56 am Post subject: |
|
|
I'm sure it's possible. Sndvol application have controls for that.
There is good example at msdn: http://msdn.microsoft.com/en-us/library/dd374921(VS.85).aspx
The chain to set volume could look like that:
| Code: | //Get IAudioSessionManager object for device
hr = pDevice->Activate(
__uuidof(IAudioSessionManager),
CLSCTX_INPROC_SERVER,
NULL,
(void**) &pAudioSessionManager
);
//Get pointer to ISimpleAudioVolume object
hr = pAudioSessionManager->GetSimpleAudioVolume(
&GUID_NULL, 0, &m_pSimpleAudioVolume
);
//Set volume
return m_pSimpleAudioVolume->SetMasterVolume(
flVolume,
&AudioSessionVolumeCtx // Event context.
); |
The only thing I can't figure is where to get session's AudioSessionVolumeCtx (in example it is declared in code)
There is session enumerator IAudioSessionEnumerator http://msdn.microsoft.com/en-us/library/dd368281(VS.85).aspx which could be used to get IAudioSessionControl.
Then IAudioSessionControl::QueryInterface could be used to get IAudioSessionControl2 http://msdn.microsoft.com/en-us/library/dd368248(VS.85).aspx
And IAudioSessionControl2 have methods: GetSessionIdentifier and GetSessionInstanceIdentifier but I not sure if its same as AudioSessionVolumeCtx...
...something wrong with [url=http://www.site.com/?(1.1)]text[/url] at forum...
Edited later:
Yes IAudioSessionControl2::GetSessionInstanceIdentifier returns value for "AudioSessionVolumeCtx" as stated in msdn: http://msdn.microsoft.com/en-us/library/dd940395(VS.85).aspx |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 4471 Location: Qld, Australia
|
Posted: Fri Aug 28, 2009 3:44 pm Post subject: |
|
|
Last time I researched this, there was no way to enumerate the audio sessions or otherwise access sessions associated with other processes. IAudioSessionEnumerator looks like it might be the go, so thanks for pointing that out. However, that interface requires Windows 7 at minimum. That's OK for me since I'm running 7 RC (soon to be running 7 RTM), but it's "off-topic" for this thread.
| Quote: | | I'm sure it's possible. Sndvol application have controls for that. | Last time I researched this, the popular consensus was that Sndvol had access to undocumented interfaces. Not knowing for sure that these interfaces even existed was obviously a significant hindrance.
| Quote: | The chain to set volume could look like that:
...
The only thing I can't figure is where to get session's AudioSessionVolumeCtx (in example it is declared in code) | No. GetSimpleAudioVolume accepts AudioSessionGuid, which identifies the session which you want an interface for. That example passes &GUID_NULL, which identifies the default session for the current process. If it is even possible to use this interface to control any session associated with another program, you must know what GUID to pass. (As far as I know it is not possible to find these values; This is what I was talking about in the first sentence of this post.)
As you've noticed, AudioSessionVolumeCtx is defined by the application; it is used in a similar way to the guidEventContext of IAudioMute:
| Quote: | EventContext
[in] Pointer to the event-context GUID. If a call to this method generates a volume-change event, the session manager sends notifications to all clients that have registered IAudioSessionEvents interfaces with the session manager. The session manager includes the EventContext pointer value with each notification. Upon receiving a notification, a client can determine whether it or another client is the source of the event by inspecting the EventContext value. This scheme depends on the client selecting a value for this parameter that is unique among all clients in the session. If the caller supplies a NULL pointer for this parameter, the client's notification method receives a NULL context pointer.
|
|
|
| Back to top |
|
 |
Yogui
Joined: 14 Jun 2008 Posts: 33 Location: Sydney, Australia
|
Posted: Mon Nov 16, 2009 10:35 pm Post subject: Windows 7 |
|
|
Hi,
Lex, you mention Win 7, is it confirm that this fuctions run in Win 7 (the 1 post mention Vista only)
Also half way in the post (Posted: Sun Nov 11, 2007 5:09 am) you gave a code to "Detect when sound is playing through the default output device. "
I can't find the function VA_GetPeakValue(peakMeter) is VA.ahk been updated and not compatible with some example previouly given.
If that the case would you be able to show the new examples:
I've collected these 2: | Code: |
;http://www.autohotkey.com/forum/topic23792.html&sid=bc6f73dd1e6a2eca3a762b14154e4f11
^1::
COM_CoInitialize()
if peakMeter := VA_GetDefaultAudioMeter()
{
Loop {
if GetKeyState("End")
break
ToolTip % VA_GetPeakValue(peakMeter) ;% display peak value since last call
Sleep, 100
}
COM_Release(peakMeter)
} else
MsgBox Failed to get peak meter.
COM_CoUninitialize()
Return
;http://www.autohotkey.com/forum/topic27425-15.html
^2::
COM_Init()
device := VA_GetDefaultAudioDevice()
device_name := VA_GetDeviceName(device)
COM_Release(device)
COM_Term()
Run, mmsys.cpl
WinWait, Sound ahk_class #32770
if InStr(device_name, "Speakers")
ControlSend, SysListView321, {Down 2} ; Headphones
else
ControlSend, SysListView321, {Down} ; Speakers
ControlClick, Button2 ; Set Default
ControlClick, Button4 ; OK
Return
|
_________________ Thanks, Yogui.
_____________________________ |
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 4471 Location: Qld, Australia
|
Posted: Tue Nov 17, 2009 10:22 am Post subject: Re: Windows 7 |
|
|
| Yogui wrote: | | Lex, you mention Win 7, is it confirm that this fuctions run in Win 7 | Yes.
| Quote: | | I can't find the function VA_GetPeakValue(peakMeter) | VA_GetPeakValue was changed in v2.0 (released on Feb 11, 2008) to be more consistent with the other "interface" functions. Please see the example in the included documentation. |
|
| Back to top |
|
 |
cruzer
Joined: 11 Feb 2009 Posts: 11
|
Posted: Fri Feb 26, 2010 12:08 am Post subject: |
|
|
I can't get it working on Windows 7 RTM 64bit.
tried to use the example script from the VA documentation:
| Code: | #Include COM.ahk
#Include VA.ahk
COM_Init()
; Get the master volume of the default playback device.
volume := VA_GetMasterVolume()
; Get the volume of the first and second channels.
volume1 := VA_GetMasterVolume(1)
volume2 := VA_GetMasterVolume(2)
; Get the master volume of a device by name.
lineout_volume := VA_GetMasterVolume("", "Line Out")
; Get the master volume of the default recording device.
recording_volume := VA_GetMasterVolume("", "capture")
MsgBox, % "Playback volume:`t" volume
. "`n Channel 1:`t" volume1
. "`n Channel 2:`t" volume2
. "`nLine Out volume:`t" lineout_volume
. "`nRecording volume:`t" recording_volume
|
and I'm getting this error:
Call to nonexistent function
in Line 147:
defaultDevice := VA_GetDevice()
the com.ahk is this:
[Moderator's note: Removed! Post a link instead.]
and va.ahk is this:
| Code: | #NoEnv
COM_CoInitialize()
pIPart := VA_GetSpeakersIPart()
text1 := VA_EnumerateSubParts_List(pIPart)
text2 := VA_EnumerateSubParts_Tree(pIPart)
COM_Release(pIPart)
Gui, Font,, Lucida Console
Gui, Add, Edit, H550 W140, %text1%
Gui, Font, s10
Gui, Add, Edit, H550 W620 YM -Wrap +0x100000, %text2%
Gui, Show,, Vista Audio Device Topology
Gui, +LastFound
WinWaitActive
Send ^{Home}
return
GuiClose:
ExitApp
; Shows a list of mute/volume components.
VA_EnumerateSubParts_List(part)
{
iid_vol := "{7FB7B48F-531D-44A2-BCB3-5AD5A134B3DC}", COM_GUID4String(iid_vol,iid_vol)
iid_mute := "{DF45AEEA-B74A-4B6B-AFAD-2366B6AA012E}", COM_GUID4String(iid_mute,iid_mute)
VA_EnumerateSubParts_List_(part, list_vol, list_mute, &iid_vol, &iid_mute)
return "VOLUME SUBUNITS`n`n" list_vol "`n`nMUTE SUBUNITS`n`n" list_mute
}
VA_EnumerateSubParts_List_(part, ByRef list_vol, ByRef list_mute, piid_vol, piid_mute)
{
static S_OK=0
; part->GetPartType()
DllCall(NumGet(NumGet(part+0)+24), "uint",part, "uint*",type)
if (type = 1) ; Subunit
{
; part->GetName(...)
; [out] LPWSTR* pwname -- (pointer to Unicode string)
DllCall(NumGet(NumGet(part+0)+12), "uint",part, "uint*",pwname)
name := COM_Ansi4Unicode(pwname), COM_CoTaskMemFree(pwname)
; part->Activate(...)
; [out] IAudioVolumeLevel iface
if (S_OK = DllCall(NumGet(NumGet(part+0)+52), "uint",part, "uint",1, "uint",piid_vol, "uint*",iface))
COM_Release(iface), list_vol .= name "`n"
; [out] IAudioMute iface
if (S_OK = DllCall(NumGet(NumGet(part+0)+52), "uint",part, "uint",1, "uint",piid_mute, "uint*",iface))
COM_Release(iface), list_mute .= name "`n"
}
; part->EnumPartsIncoming(...)
; [out] IPartsList parts
DllCall(NumGet(NumGet(part+0)+40), "uint",part, "uint*",parts)
; parts->GetCount()
DllCall(NumGet(NumGet(parts+0)+12), "uint",parts, "uint*",count)
Loop, %count%
{
; parts->GetPart(A_Index-1, [out] subpart)
DllCall(NumGet(NumGet(parts+0)+16), "uint",parts, "uint",A_Index-1, "uint*",subpart)
; RECURSE
VA_EnumerateSubParts_List_(subpart, list_vol, list_mute, piid_vol, piid_mute)
COM_Release(subpart)
}
}
; Shows the device topology in tree form.
VA_EnumerateSubParts_Tree(part)
{
static indent, indent_size=3
; Friendly names for common interfaces.
static iid_DF45AEEA_B74A_4B6B_AFAD_2366B6AA012E="IAudioMute"
, iid_7FB7B48F_531D_44A2_BCB3_5AD5A134B3DC="IAudioVolumeLevel"
, iid_85401FD4_6DE4_4B9D_9869_2D6753A82F3C="IAudioAutoGainControl"
; part->GetName(...)
; [out] LPWSTR* pwname -- (pointer to Unicode string)
DllCall(NumGet(NumGet(part+0)+12), "uint",part, "uint*",pwname)
; part->GetPartType()
DllCall(NumGet(NumGet(part+0)+24), "uint",part, "uint*",type)
name := COM_Ansi4Unicode(pwname), COM_CoTaskMemFree(pwname)
text .= indent "+ "
if (type != 1) ; not a subunit
text .= type=0 ? "(CONNECTOR) " : "(UNKNOWN) "
text .= name
; connPart->GetControlInterfaceCount(count)
DllCall(NumGet(NumGet(part+0)+32), "uint",part, "uint*",count)
Loop, %count%
{
; connPart->GetControlInterface(...)
; [out] IControlInterface idesc
DllCall(NumGet(NumGet(part+0)+36), "uint",part, "uint",A_Index-1, "uint*",idesc)
; idesc->GetIID(...)
; [out] GUID iid
VarSetCapacity(iid, 16)
DllCall(NumGet(NumGet(idesc+0)+16), "uint",idesc, "uint",&iid)
iid := COM_String4GUID(&iid)
StringReplace, iids, iid, -, _, All
StringTrimLeft, iids, iids, 1
StringTrimRight, iids, iids, 1
if iid_%iids%
iids := iid_%iids%
else
iids := iid
text .= A_Index>1 ? ", " iids : " : " iids
COM_Release(idesc), idesc=0
}
text .= "`n"
Loop, %indent_size%
indent .= A_Space
; part->EnumPartsIncoming(...)
; [out] IPartsList parts
DllCall(NumGet(NumGet(part+0)+40), "uint",part, "uint*",parts)
; parts->GetCount()
DllCall(NumGet(NumGet(parts+0)+12), "uint",parts, "uint*",count)
Loop, %count%
{
; parts->GetPart(A_Index-1)
DllCall(NumGet(NumGet(parts+0)+16), "uint",parts, "uint",A_Index-1, "uint*",subpart)
text .= VA_EnumerateSubParts_Tree(subpart)
COM_Release(subpart)
}
indent := SubStr(indent,1,-indent_size)
return text
}
; Gets a pointer to an IPart interface that represents the Speakers.
VA_GetSpeakersIPart()
{
defaultDevice := VA_GetDevice()
; defaultDevice->Activate(...)
; [out] IDeviceTopology deviceTopology
iid := "{2A07407E-6497-4A18-9787-32F79BD0D98F}"
DllCall(NumGet(NumGet(defaultDevice+0)+12), "uint",defaultDevice, "uint",COM_GUID4String(iid,iid), "uint",1, "uint",0, "uint*",deviceTopology)
COM_Release(defaultDevice), defaultDevice=0
; deviceTopology->GetConnector(0,...)
; [out] IConnector endptConnector
DllCall(NumGet(NumGet(deviceTopology+0)+16), "uint",deviceTopology, "uint",0, "uint*",endptConnector)
COM_Release(deviceTopology), deviceTopology=0
; endptConnector->GetConnectedTo(...)
; [out] IConnector hwdevConnector
DllCall(NumGet(NumGet(endptConnector+0)+32), "uint",endptConnector, "uint*",hwdevConnector)
COM_Release(endptConnector), endptConnector=0
; hwdevConnector->QueryInterface(...)
; [out] IPart connPart
iid := "{AE2DE0E4-5BCA-4F2D-AA46-5D13F8FDB3A9}"
connPart := COM_QueryInterface(hwdevConnector, iid)
COM_Release(hwdevConnector), hwdevConnector=0
return connPart
} |
|
|
| Back to top |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 4471 Location: Qld, Australia
|
Posted: Fri Feb 26, 2010 9:30 am Post subject: Re: Vista Audio Control Functions v2.0 |
|
|
| You've copied the wrong script, which clearly doesn't contain VA_GetDevice. In my first post click the Download with documentation link. I've replaced the device topology script with a link to avoid any further confusion. |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|