예제 #1
0
        static IntPtr tapEventCallback(IntPtr proxy, CGEventType type, IntPtr evtHandle, IntPtr info)
        {
            using (new NSAutoreleasePool()) {
                var evt = new CGEvent(evtHandle);
                if (!SPMediaKeyTap.Shared.ShouldInterceptMediaKeyEvents)
                {
                    return(evtHandle);
                }
                switch (type)
                {
                //kCGEventTapDisabledByTimeout
                case  (CGEventType)kCGEventTapDisabledByTimeout:
                    CGEvent.TapEnable(SPMediaKeyTap.Shared.eventPort);
                    return(evtHandle);

                case (CGEventType)kCGEventTapDisabledByUser:
                    return(evtHandle);
                }

                NSEvent nsEvent = null;
                try{
                    nsEvent = NSEvent.EventWithCGEvent(evtHandle);
                }
                catch (Exception ex) {
                    return(evtHandle);
                }

                if (nsEvent.Subtype != SPSystemDefinedEventMediaKeys)
                {
                    return(evtHandle);
                }
                long keyCode = ((nsEvent.Data1 & 0xFFFF0000) >> 16);

                var keyFlags = (nsEvent.Data1 & 0x0000FFFF);

                var keyState = (((keyFlags & 0xFF00) >> 8)) == 0xA;
                if (keyCode == 10 && keyFlags == 6972)
                {
                    switch (nsEvent.Data2)
                    {
                    case 786608:                     // Play / Pause on OS < 10.10 Yosemite
                    case 786637:                     // Play / Pause on OS >= 10.10 Yosemite
                        Console.WriteLine(@"Play/Pause bluetooth keypress detected...sending corresponding media key event");
                        SPMediaKeyTap.Shared.RecievedEvent(MediaKey.Play);
                        break;

                    case 786611:                     // Next
                        Console.WriteLine(@"Next bluetooth keypress detected...sending corresponding media key event");
                        SPMediaKeyTap.Shared.RecievedEvent(MediaKey.Next);
                        break;

                    case 786612:                     // Previous
                        Console.WriteLine(@"Previous bluetooth keypress detected...sending corresponding media key event");
                        SPMediaKeyTap.Shared.RecievedEvent(MediaKey.Previous);
                        break;

                    case 786613:                     // Fast-forward
                        Console.WriteLine(@"Fast-forward bluetooth keypress detected...sending corresponding media key event");
                        SPMediaKeyTap.Shared.RecievedEvent(MediaKey.Fast);
                        break;

                    case 786614:                     // Rewind
                        Console.WriteLine(@"Rewind bluetooth keypress detected...sending corresponding media key event");
                        SPMediaKeyTap.Shared.RecievedEvent(MediaKey.Rewind);
                        break;

                    default:
                        // TODO make this popup a message in the UI (with a link to submit the issue and a "don't show this message again" checkbox)
                        LogManager.Shared.Log($"Unknown bluetooth key received: keyCode:{keyCode} keyFlags:{keyFlags} keyState:{keyState} {nsEvent.Data2}");
                        return(evtHandle);
                    }
                }
                else
                {
                    if (keyCode != NX_KEYTYPE_PLAY && keyCode != NX_KEYTYPE_FAST && keyCode != NX_KEYTYPE_REWIND && keyCode != NX_KEYTYPE_PREVIOUS && keyCode != NX_KEYTYPE_NEXT)
                    {
                        return(evtHandle);
                    }
                    //These always come in pairs
                    if (lastKeyCode != keyCode)
                    {
                        SPMediaKeyTap.Shared.BeginInvokeOnMainThread(() => {
                            SPMediaKeyTap.Shared.RecievedEvent((MediaKey)keyCode);
                        });
                        lastKeyCode = keyCode;
                    }
                    else
                    {
                        lastKeyCode = 0;
                    }
                }
                evt.Dispose();
                return(IntPtr.Zero);
            }
        }