3

I have an app which can change the volume under OSX. What it lacks is the visual feedback provided when one presses the sound up/down keys. Does anyone know how to programmatically invoke that behavior? Thanks

Lazloman
  • 1,289
  • 5
  • 25
  • 50

2 Answers2

7

Here's a little code from George Warner and Casey Fleser that does this trick. Think carefully that this is really the way you want to do things.

// Save as sound_up.m
// Compile: gcc -o sound_up sound_up.m -framework IOKit -framework Cocoa

#import <Cocoa/Cocoa.h>
#import <IOKit/hidsystem/IOHIDLib.h>
#import <IOKit/hidsystem/ev_keymap.h>


static io_connect_t get_event_driver(void)
{
    static  mach_port_t sEventDrvrRef = 0;
    mach_port_t masterPort, service, iter;
    kern_return_t    kr;

    if (!sEventDrvrRef)
    {
        // Get master device port
        kr = IOMasterPort( bootstrap_port, &masterPort );
        check( KERN_SUCCESS == kr);

        kr = IOServiceGetMatchingServices( masterPort, IOServiceMatching( kIOHIDSystemClass ), &iter );
        check( KERN_SUCCESS == kr);

        service = IOIteratorNext( iter );
        check( service );

        kr = IOServiceOpen( service, mach_task_self(),
                            kIOHIDParamConnectType, &sEventDrvrRef );
        check( KERN_SUCCESS == kr );

        IOObjectRelease( service );
        IOObjectRelease( iter );
    }
    return sEventDrvrRef;
}


static void HIDPostAuxKey( const UInt8 auxKeyCode )
{
  NXEventData   event;
  kern_return_t kr;
  IOGPoint      loc = { 0, 0 };

  // Key press event
  UInt32      evtInfo = auxKeyCode << 16 | NX_KEYDOWN << 8;
  bzero(&event, sizeof(NXEventData));
  event.compound.subType = NX_SUBTYPE_AUX_CONTROL_BUTTONS;
  event.compound.misc.L[0] = evtInfo;
  kr = IOHIDPostEvent( get_event_driver(), NX_SYSDEFINED, loc, &event, kNXEventDataVersion, 0, FALSE );
  check( KERN_SUCCESS == kr );

  // Key release event
  evtInfo = auxKeyCode << 16 | NX_KEYUP << 8;
  bzero(&event, sizeof(NXEventData));
  event.compound.subType = NX_SUBTYPE_AUX_CONTROL_BUTTONS;
  event.compound.misc.L[0] = evtInfo;
  kr = IOHIDPostEvent( get_event_driver(), NX_SYSDEFINED, loc, &event, kNXEventDataVersion, 0, FALSE );
  check( KERN_SUCCESS == kr );

}

int main(int argc, char *argv[]) {
  HIDPostAuxKey(NX_KEYTYPE_SOUND_UP);
}

Other interesting keycodes include: NX_KEYTYPE_SOUND_DOWN, NX_KEYTYPE_MUTE, NX_KEYTYPE_PLAY.

  • Ah, so IOKit stuff may be needed. I'm going to take a look at this and see how it works out. – Lazloman May 11 '12 at 00:29
  • This actually raises/lowers the volume in full increments, i.e. one "block" at a time. What I want to do is recreate the behavior that existed pre-Lion, when one could press the option key and the up/down button and the volume would increase/decrease in fractional amounts, i.e. a quarter of a block. I can increase/decrease the volume in code by fractional amounts, and I want to get the OS to report that fractional increase/decrease in volume by those same fractional amounts, i.e., a quarter block at a time. I'll look through IOKit and see if I can do this, thanks, this gives me some ideas. – Lazloman May 12 '12 at 20:30
0

I would implement this by simulating the physical press of the up/down volume keys, and letting the OS deal with the details. Perhaps the user has disabled the visual feedback, perhaps it changes, etc. - this is the safest way of pulling it off.

Have a look at this: Simulating key press events in Mac OS X

Community
  • 1
  • 1
Mahmoud Al-Qudsi
  • 28,357
  • 12
  • 85
  • 125
  • I thought about, and I should have been clearer, but what I'm doing is raising/lowering the volume in smaller increments than the key presses would do. I expect that if I post key events, I'll end up with the standard increment in volume instead of the fraction increments as intended. – Lazloman Apr 23 '12 at 01:38
  • In that case, honestly, you probably should not be trying to use the default OS X volume notification thingy because it indicates the level as an atomic increment/decrement of one block - it could be misleading if shown when the user is actually making, as you say, much finer changes. – Mahmoud Al-Qudsi Apr 23 '12 at 03:04
  • I'm trying to re-create the behavior that existed before Lion. Are you saying that this is not possible anymore? – Lazloman Apr 23 '12 at 17:18
  • 1
    you could always post the key events with shift+alt(vol up/down) to control the vol in smaller increments. – drunknbass Oct 25 '12 at 07:43