如何通过macOS命令行工具使用Apple的GameController框架? [英] How do I use Apple's GameController framework from a macOS Command Line Tool?

查看:66
本文介绍了如何通过macOS命令行工具使用Apple的GameController框架?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试获取以下代码以用作macOS命令行工具.一定不要将它作为可可应用,因此这不是一个选择.

I'm trying to get the following code to work as a macOS command line tool. It is important that this not be a Cocoa app, so that is not an option.

同一代码可在同一项目中与Cocoa App目标完美配合,并检测到兼容的控制器,但是当作为命令行工具目标运行时,什么也没有发生,并且API显示未连接任何控制器.

This same code works perfectly in the same project with a Cocoa App target and detects a compatible controller, but when run as a Command Line Tool target, nothing happens and the API shows no controllers connected.

显然,其中一些是人为设计的……这是我可以将其归结为最简单的方法,并且可以在实际工作时对发生的事情有所提示.

Obviously, some of it is contrived... it's just the simplest I could boil it down to and have some indication of things happening when it actually works.

#import <Cocoa/Cocoa.h>
#import <GameController/GameController.h>


int main( int argc, const char * argv[] )
{
    @autoreleasepool
    {
        NSApplication * application = [NSApplication sharedApplication];

        NSNotificationCenter * center = [NSNotificationCenter defaultCenter];

        [center addObserverForName: GCControllerDidConnectNotification
                            object: nil
                             queue: nil
                        usingBlock: ^(NSNotification * note) {
                            GCController * controller = note.object;
                            printf( "ATTACHED: %s\n", controller.vendorName.UTF8String );
                        }
         ];

        [application finishLaunching];

        bool shouldKeepRunning = true;
        while (shouldKeepRunning)
        {
            printf( "." );

            while (true)
            {
                NSEvent * event = [application
                                   nextEventMatchingMask: NSEventMaskAny
                                   untilDate: nil
                                   inMode: NSDefaultRunLoopMode
                                   dequeue: YES];
                if (event == NULL)
                {
                    break;
                }
                else
                {
                    [application sendEvent: event];
                }
            }

            usleep( 100 * 1000 );
        }
    }

    return 0;
}

我猜想这与Cocoa应用程序的设置或事件循环的处理方式有关.也许有一些内部触发器可以初始化GameController框架.该API似乎没有任何明确的初始化方法.

I'm guessing it's got something to do with how the Cocoa application sets up or the event loops are handled. Or maybe there's some internal trigger that initializes the GameController framework. The API doesn't appear to have any explicit way to initialize it.

https://developer.apple.com/documentation/gamecontroller?language=objc

任何人都可以阐明我如何使它工作吗?

Can anyone shed some light on how I might get this working?

最终,此代码确实需要在Core Foundation捆绑软件中工作,因此,如果它实际上可以与理想的Core Foundation Runloop一起工作.

Ultimately, this code really needs to work inside a Core Foundation bundle, so if it could actually work with a Core Foundation runloop that would be ideal.

-编辑-

我做了一个测试项目,以更清楚地说明问题.有两个构建目标.Cocoa应用程序构建目标工作并接收到控制器已连接事件.另一个构建目标,只是一个简单的CLI应用程序,无法正常工作.它们都使用相同的源文件.它还包括两个代码路径,其中一个是传统的[NSApp运行],第二个是上面的手动事件循环.结果是一样的.

I have made a test project to illustrate the problem more clearly. There are two build targets. The Cocoa app build target works and receives the controller connected event. The other build target, just a simple CLI app, does not work. They both use the same source file. It also includes two code paths, one of which is the traditional [NSApp run], the second is the manual event loop above. The result is the same.

https://www.dropbox.com/s/a6fw3nuegq7bg8x/ControllerTest.zip?dl=0

推荐答案

我使用以下main.m文件进行此操作:

I have this working with the following main.m file:

#import <AppKit/AppKit.h>
#import <GameController/GameController.h>

@interface AppDelegate : NSObject<NSApplicationDelegate> @end

@implementation AppDelegate
- (void) applicationDidFinishLaunching: (NSNotification*) notification {
    [NSApp stop: nil]; // Allows [app run] to return
}
@end

int main() {
    NSApplication* app = [NSApplication sharedApplication];
    [app setActivationPolicy: NSApplicationActivationPolicyRegular];
    [app setDelegate: [[AppDelegate alloc] init]];
    [app run];

    // 1 with a DualShock 4 plugged in
    printf("controllers %lu\n", [[GCController controllers] count]);

    // Do stuff here

    return 0;
}

编译为: clang -framework AppKit -framework GameController main.m

我不知道为什么,但是我需要在构建输出目录中有一个Info.plist文件.没有它,controllers数组将不会被填充.这是我的整个文件:

I have no idea why, but I need an Info.plist file in the build output directory. Without it, the controllers array doesn't get populated. This is my entire file:

<dict>
    <key>CFBundleIdentifier</key>
    <string>your.bundle.id</string>
</dict>

我不确定提供Info.plist可能有什么含义,但是如果存在,我可以像往常一样运行a.out可执行文件,并得到我的控制器数组.

I'm not sure what implications supplying an Info.plist might have, but if it's there, I can run the a.out executable as normal and I get my controllers array.

这篇关于如何通过macOS命令行工具使用Apple的GameController框架?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆