防止错误"放克"事件监视器OS X中的声音

时间:2016-12-26 17:28:36

标签: swift macos menubar

我正在swift中编写一个应用程序,它位于屏幕顶部的菜单栏中。我需要一个全局和本地事件监视器来打开特定按键上的弹出窗口。本地事件监视器没有问题,但是当用户从像Finder这样的应用程序内部命中键命令(cmd + shift + 8)时,弹出窗口会打开,但是mac错误" Funk"声音也播放。有什么方法可以禁用它吗?也许某种方式让应用程序吃掉声音,或将其注册为有效的键盘快捷键,以便从未播放声音?

以下是代码:

        NSEvent.addGlobalMonitorForEvents(matching: NSEventMask.keyDown, handler: {(event: NSEvent!) -> Void in
        if (event.keyCode == 28 && event.modifierFlags.contains(NSEventModifierFlags.command) && event.modifierFlags.contains(NSEventModifierFlags.shift)){
            self.togglePopover(sender: self)
        }
    });

    NSEvent.addLocalMonitorForEvents(matching: NSEventMask.keyDown, handler: {(event: NSEvent!) -> NSEvent? in
        if (event.keyCode == 28 && event.modifierFlags.contains(NSEventModifierFlags.command) && event.modifierFlags.contains(NSEventModifierFlags.shift)){
            self.togglePopover(sender: self)
        }
        return event
    });

2 个答案:

答案 0 :(得分:0)

我最终使用MASShortcut作为此问题的解决方案。

答案 1 :(得分:0)

  1. 在您的addGlobalMonitorForEventsMatchingMask处理程序中,保存当前音量级别并在两个通道上调低音量。您可以在调低音量之前或之后在处理程序中进行事件处理。

  2. 从处理程序返回之前,请还原原始卷,但要留出一定的延迟以使OS有时间处理事件(它将发送“ funk”,但您不会听到)。

一个副作用:如果您正在听某些东西(例如音乐),那也会短暂地静音。

我的活动代码:

[NSEvent addGlobalMonitorForEventsMatchingMask:NSEventMaskKeyDown
                                       handler:^(NSEvent *event) {
    if ( event.type == NSEventTypeKeyDown ) {
        if ( event.keyCode == 106 ) { // F16
            // process the event here
            [self adjustVolume:@(NO)];
            [self performSelector:@selector(adjustVolume:) withObject:@(YES) afterDelay:0.3];
            // 0.2 seconds was too soon
        }
    }
}];

我的音量调节代码:

- (void)adjustVolume:(NSNumber *)offOn
{
    // get audio device...
    AudioObjectPropertyAddress getDefaultOutputDevicePropertyAddress = {
        kAudioHardwarePropertyDefaultOutputDevice,
        kAudioObjectPropertyScopeGlobal,
        kAudioObjectPropertyElementMaster
    };

    AudioDeviceID defaultOutputDeviceID;
    UInt32 infoSize = sizeof(defaultOutputDeviceID);
    AudioObjectGetPropertyData(kAudioObjectSystemObject,
                               &getDefaultOutputDevicePropertyAddress,
                               0, NULL,
                               &infoSize, &defaultOutputDeviceID);

    // structurs to access the left/right volume setting
    AudioObjectPropertyAddress volumePropertyAddress1 = {
        kAudioDevicePropertyVolumeScalar,
        kAudioDevicePropertyScopeOutput,
        1 /* left */
    };
    AudioObjectPropertyAddress volumePropertyAddress2 = {
        kAudioDevicePropertyVolumeScalar,
        kAudioDevicePropertyScopeOutput,
        2 /* right */
    };

    // save the original volume (assumes left/right are the same
    static Float32 volumeOriginal; // could be an iVar

    if ( offOn.boolValue == NO ) { // turn off 

        UInt32 volumedataSize = sizeof(volumeOriginal);
        AudioObjectGetPropertyData(defaultOutputDeviceID,
                                   &volumePropertyAddress1,
                                   0, NULL,
                                   &volumedataSize, &volumeOriginal);
        //NSLog(@"volumeOriginal %f",volumeOriginal);

        // turn off both channels
        Float32 volume = 0.0;
        AudioObjectSetPropertyData(defaultOutputDeviceID,
                                   &volumePropertyAddress1,
                                   0, NULL,
                                   sizeof(volume), &volume);
        AudioObjectSetPropertyData(defaultOutputDeviceID,
                                   &volumePropertyAddress2,
                                   0, NULL,
                                   sizeof(volume), &volume);

    } else { // restore

        //NSLog(@"restoring volume");
        AudioObjectSetPropertyData(defaultOutputDeviceID,
                                   &volumePropertyAddress1,
                                   0, NULL,
                                   sizeof(volumeOriginal), &volumeOriginal);
        AudioObjectSetPropertyData(defaultOutputDeviceID,
                                   &volumePropertyAddress2,
                                   0, NULL,
                                   sizeof(volumeOriginal), &volumeOriginal);
    }
}

感谢Thomas O'Dell帮助我开始使用此Change OS X system volume programmatically