Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Programmatically enable/disable a playback device in Windows 7

by thmsdrew (Scribe)
on Nov 08, 2012 at 13:34 UTC ( [id://1002892]=perlquestion: print w/replies, xml ) Need Help??

thmsdrew has asked for the wisdom of the Perl Monks concerning the following question:

Hello folks. My goal is to programmatically enable or disable playback devices in Windows 7. I have headphones and speakers that I switch between frequently enough that it would be nice to automate it. Right now, if I want to switch between the two, I have to right-click the sound icon in my taskbar, click "Playback devices", right-click the currently enabled device, disabling it, and then right-click the disabled one, enabling it.

I've already looked into Microsoft's DevCon tool. It almost does what I describe, except it can only enable/disable the entire HDAUDIO device. I want to enable/disable either "Headphones" or "Speakers", which I don't think are given individual device IDs.

I did a bit of CPAN searching and didn't find much. I'm thinking maybe there's an automation "suite" that can access windows and click stuff within them. (XPath or something).

Any ideas?

Edit: I can programmatically open up the sound options window I'm talking about with the following command:

C:\> control mmsys.cpl

Just need to be able to identify entities within the window and left- or right-click on them. I think Win32::GuiTest can do that.

Double Edit: This is how I am doing it, for anyone that still cares:

Enable headphones:

#!/usr/bin/perl use strict; use warnings; use Win32::GuiTest qw(FindWindowLike GetWindowRect MouseMoveAbsPix Sen +dMouse SendKeys SetForegroundWindow PushButton); system "control mmsys.cpl"; sleep 1; my @sound = FindWindowLike(undef, "Sound"); my @list = FindWindowLike($sound[0], "", "SysListView32"); my ($left, $top, $right, $bottom) = GetWindowRect($list[0]); MouseMoveAbsPix($right - 7, $top + 57); SendMouse("{RightClick}"); SendKeys("{E}"); MouseMoveAbsPix($right - 7, $top + 112); SendMouse("{RightClick}"); SendKeys("{D}"); SetForegroundWindow($sound[0]); PushButton("OK");

Enable speakers:

#!/usr/bin/perl use strict; use warnings; use Win32::GuiTest qw(FindWindowLike GetWindowRect MouseMoveAbsPix Sen +dMouse SendKeys SetForegroundWindow PushButton); system "control mmsys.cpl"; sleep 1; my @sound = FindWindowLike(undef, "Sound"); my @list = FindWindowLike($sound[0], "", "SysListView32"); my ($left, $top, $right, $bottom) = GetWindowRect($list[0]); MouseMoveAbsPix($right - 7, $top + 57); SendMouse("{RightClick}"); SendKeys("{D}"); MouseMoveAbsPix($right - 7, $top + 112); SendMouse("{RightClick}"); SendKeys("{E}"); SetForegroundWindow($sound[0]); PushButton("OK");

Replies are listed 'Best First'.
Re: Programmatically enable/disable a playback device in Windows 7
by Anonymous Monk on Nov 08, 2012 at 17:09 UTC
Re: Programmatically enable/disable a playback device in Windows 7
by bulk88 (Priest) on Nov 08, 2012 at 16:31 UTC
    winmm.dll or msacm32.dll probably have what you are looking for. I only have NT 5 machines not NT 6. I don't understand exactly, GUI with a mouse wise, what you are trying to do. Can you post some links to images of the screens you want to manipulate? If it doesn't appear in Device Manager, it won't appear in devcon.

    Look for some C code that claims to do what you want, then look for perl or code that contains the same function name.

      This is the screen I'm talking about. If I want to hear sound out of just my speakers, I have to enable "Speakers" and disable "Headphones". If I want to hear sound out of just my headphones, I have to enable "Headphones" and disable "Speakers". (Right-click -> enable/disable).

      They both use the HDAUDIO device.

      I'll look into those libraries you gave.

Re: Programmatically enable/disable a playback device in Windows 7
by bulk88 (Priest) on Nov 09, 2012 at 04:32 UTC
Re: Programmatically enable/disable a playback device in Windows 7
by thmsdrew (Scribe) on Nov 09, 2012 at 02:27 UTC

    What I am thinking of doing is the following:

    #!/usr/bin/perl use strict; use warnings; use Win32::GuiTest qw(:ALL); system "control mmsys.cpl"; sleep 1; my @sound = FindWindowLike(undef, "Sound"); # Get the list that contains the playback devices my @list = FindWindowLike($sound[0], "", "SysListView32"); my ($left, $top, $right, $bottom) = GetWindowRect($list[0]); # Move the mouse within the bounds of that list, clicking # on stuff. You can type "E" to enable the device once you # right-click, or "D" to disable it. MouseMoveAbsPix($right - 10, $top + 5); SendMouse("{RightClick}"); SendKeys("{E}");

    It's limited in that I have to trial-and-error to find the right pixels to click. As far as I'm concerned, there's no way to find the coordinates of the individual list items, so I think something like this will have to do. Any thoughts?

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1002892]
Approved by Corion
Front-paged by bulk88
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (6)
As of 2024-04-16 08:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found