Ryan Ballantyne
Ryan Ballantyne

Reputation: 4094

Implementing keyboard volume control buttons in Applescript - setting volume inside loop doesn't work

Background

I have a MacAlly IceKey keyboard. This keyboard has volume buttons that require a driver to function. This driver has not been updated since 2006, and I suspect it as the source of a recent spat of recurring kernel panics I've been experiencing under Mac OS X 10.6.1. So, out it goes; but I want my volume keys back!

Using the wonderful ControllerMate, I can program these keys to do anything, including run an applescript script. So, I'm trying to implement that functionality.

The set volume command (part of Standard Additions) allows you to set the volume to any value between 0 and 100. The Apple keyboard volume keys allow a total of 17 volume settings to be selected (including 0). I figure the simplest way to duplicate this behavior is to keep a list of allowed volume settings and grab the next largest (or smallest) one out of that.

The problem

It doesn't work. The following script:

set volumesList to {0, 6, 12, 18, 25, 31, 37, 43, 50, 56, 62, 68, 75, 81, 87, 93, 100}
set sysVolume to get volume settings

repeat with curVolume in volumesList
    if (curVolume > (output volume of sysVolume)) then
        set volume output volume (contents of curVolume)
        exit repeat
    end if
end repeat

get volume settings

...only works if the system volume level happens to be less than 43. The system seems to interpret "50" as "49"; that's as high as the volume will go with my script. If the volume starts higher than 50, my script has no effect. The kicker? If the "exit repeat" statement is removed, the system volume gets set to 100 - just as you'd expect.

(Good grief, AppleScript is weird sometimes.)

Any ideas?

Bonus Points

It would be super awesome to get this to display the volume overlay as well. Does anyone know how to accomplish that? It doesn't even need to be through AppleScript; I'm happy sticking some Cocoa code in a command-line tool if that's what it takes.

Upvotes: 5

Views: 3522

Answers (3)

Chris
Chris

Reputation: 7310

You can also use the built in notification

set vol to ((output volume of (get volume settings)) + 5)
if (vol > 100) then set vol to 100
set volume output volume (vol)

display notification ((vol) as string)

Upvotes: 2

binarymochi
binarymochi

Reputation: 113

With a paid nerd's suggestions for crafting a Growl notification, I made a Mute/Unmute version of this that displays a Growl notification, but only for a brief moment.

Since I couldn't find a way to specify a growl duration and style, I used applescript to read the current growl defaults, switch over to a simple Growl style (Smoke, since it shows just a little window in the upper right corner, though you could adapt this script to Bezel for behavior that more perfectly mirrors the system), drops the delay to 0.3 seconds, growls, then reverts growl's prefs.

The script is a bit verbose, as I have mostly forgotten applescript. I'm sure there's a way to simplify this much more.

set _muted to (get (output muted of (get volume settings)))
set str to "Muted"
if _muted is false then
    set volume with output muted
else
    set volume without output muted
    set str to "" & output volume of (get volume settings)
end if

set oldStyle to (do shell script "defaults read com.Growl.GrowlHelperApp GrowlDisplayPluginName")

do shell script "defaults write com.Growl.GrowlHelperApp GrowlDisplayPluginName Smoke"

set alpha to (do shell script "defaults read com.Growl.GrowlHelperApp com.growl.SmokeNotificationView | awk '$3 ~ /Alpha/' | sed -E 's/[^0-9.]*//g'")

set duration to (do shell script "defaults read com.Growl.GrowlHelperApp com.growl.SmokeNotificationView | awk '$3 ~ /Duration/' | sed -E 's/[^0-9.]*//g'")

set cmd to "defaults write com.Growl.GrowlHelperApp \"com.growl.SmokeNotificationView\" -dict "
set params to "\"Smoke - Alpha\" -float " & alpha & " \"Smoke - Duration\" -float 0.3"

do shell script cmd & params

tell application "GrowlHelperApp"
    register as application ¬
        "Volume Change" all notifications {"Volume Change"} ¬
        default notifications {"Volume Change"} ¬
        icon of application "Script Editor"

    notify with name ¬
        "Volume Change" title "Volume" description str application name ¬
        "Volume Change" identifier "MuteUnmute"
end tell

do shell script "defaults write com.Growl.GrowlHelperApp GrowlDisplayPluginName " & oldStyle

set params to "\"Smoke - Alpha\" -float " & alpha & " \"Smoke - Duration\" -float " & duration
do shell script cmd & params

Upvotes: 1

a paid nerd
a paid nerd

Reputation: 31532

I have no idea how to get the translucent overlay to show up, but this at least plays the system beep while turning the volume up:

set currentVolume to output volume of (get volume settings)
set newVolume to (currentVolume + (100 / 17)) as integer
set volume output volume newVolume
beep

Replace the + with a - in your volume-down script.

set volume output seems to be automatically adjust values outside the (0, 100) limit.

Update: You could use Growl's AppleScript support to show some kind of overlay:

tell application "GrowlHelperApp"

    register as application "Volume Change" ¬
        all notifications {"Volume Change"} ¬
        default notifications {"Volume Change"} ¬
        icon of application "Script Editor"

    notify with name "Volume Change" ¬
        title "Volume Up" ¬
        description "Volume is now " & output volume of (get volume settings) ¬
        application name "Volume Change"

end tell

Upvotes: 7

Related Questions