微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为 NodeJS 运行我的 C++ 插件时,PortMidi Pm_OpenInput() 函数崩溃

如何解决为 NodeJS 运行我的 C++ 插件时,PortMidi Pm_OpenInput() 函数崩溃

我正在尝试使用 ElectronC++ 插件 制作一个简单的 DAW,并且我想使用 PortMidi支持 Midi 键盘。 我制作了一个 midi.h 脚本来查看 PortMidi 是否有效,并且我设法使用 mingw-g++ 编译和运行该脚本(并且它有效),但是当我使用 node-gyp 构建 nodejs 插件,并运行应用程序,它在执行 Pm_OpenInput(&midi_in,id,NULL,NULL); 期间显示错误(我认为这意味着 C++ 脚本无缘无故停止了......)

npm ERR! code ELIFECYCLE
npm ERR! errno 4294930435
npm ERR! fynewav@0.1.0 start: `electron ./server/main.js`
npm ERR! Exit status 4294930435
npm ERR!
npm ERR! Failed at the fynewav@0.1.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

我在 .lib文件夹中使用此命令从这个 github 存储库 https://github.com/philandstuff/portmidiPortMidi 自己生成.dll/build/ 文件

 cmake .. -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL -DBUILD_SHARED_LIBS:BOOL=ON -DPM_CHECK_ERRORS=ON; cmake --build .

这是我的 midi.h 文件

#include <iostream>
#include <thread>
#include "portmidi.h"

#define MIDI_SYSEX 0xf0
#define MIDI_EOX 0xf7

int active = FALSE;
bool running = true;
std::thread midiThread;

PmStream *midi_in;

int thru_sysex_in_progress = FALSE;
int app_sysex_in_progress = FALSE;

void process_midi()
{
    while (running)
    {
        PmError result;
        PmEvent buffer;

        if (!active) continue;

        if (!app_sysex_in_progress) {
            do {
                result = Pm_Poll(midi_in);
                if (result) {
                    int status;
                    int rslt = Pm_Read(midi_in,&buffer,1);
                    if (rslt == pmBufferOverflow) 
                        continue;

                    status = Pm_MessageStatus(buffer.message);
                    if (((status & 0x80) == 0) && !thru_sysex_in_progress) {
                        continue; /* sysex old data,ignore */
                    }

                    int i = Pm_MessageData1(buffer.message);
                    int i2 = Pm_MessageData2(buffer.message);
                    int s = Pm_MessageStatus(buffer.message);
                    printf("Note %d - Force %d - State %s\n",i,i2,(s==128)? "Off": "On");

                    /* sysex processing */
                    if (status == MIDI_SYSEX) thru_sysex_in_progress = TRUE;
                    else if ((status & 0xF8) != 0xF8) {
                        /* not MIDI_SYSEX and not real-time,so */
                        thru_sysex_in_progress = FALSE;
                    }
                    if (thru_sysex_in_progress && /* look for EOX */
                        (((buffer.message & 0xFF) == MIDI_EOX) ||
                        (((buffer.message >> 8) & 0xFF) == MIDI_EOX) ||
                        (((buffer.message >> 16) & 0xFF) == MIDI_EOX) ||
                        (((buffer.message >> 24) & 0xFF) == MIDI_EOX))) {
                        thru_sysex_in_progress = FALSE;
                    }
                    if (thru_sysex_in_progress)
                        std::cout << "sysex in progress" << std::endl;
                }
            } while (result);
        }
    }
}

void portopen()
{
    const PmDeviceInfo *info;
    Pmdeviceid id;

    PmError err =  Pm_Initialize();

    midiThread = std::thread(process_midi);
    
    id = Pm_GetDefaultInputdeviceid();
    info = Pm_GetDeviceInfo(id);
    
    if (info == nullptr)
    {
        std::cout << "No Midi device found" << std::endl;
        return;
    }
    printf("opening input device %s %s\n",info->interf,info->name);
    
    Pm_OpenInput(&midi_in,NULL);
    
    Pm_SetFilter(midi_in,PM_FILT_ACTIVE | PM_FILT_CLOCK);
    active = true;
    return;
}

void portClose()
{
    active = false;
    running = false;
    
    midiThread.join();

    Pm_Close(midi_in);
    Pm_Terminate();
}

这是我用 mingw-g++ 编译的 main.cpp 文件来尝试 PortMidi(它适用于 g++)

#include "midi.h"

int main(int argc,char const *argv[])
{
    portopen();
    std::this_thread::sleep_for(std::chrono::seconds(5));
    portClose();
}

这是我用于 node-gypbinding.gyp 文件:(我只为 Windows 制作了正确的包含)

{
    "targets": [
        {
            "target_name": "engine","sources": [ "./engine/wrapper.cpp" ],"include_dirs": [
                "<(module_root_dir)/engine/include/","<!@(node -p \"require('node-addon-api').include\")"
            ],'conditions': [
                ['OS=="win"',{
                    'defines': [
                    '__WINDOWS_MM__'
                    ],'link_settings': {
                        'libraries': [
                            "-lOpenAL32","-lsndfile","-lportmidi"
                        ],'library_dirs': [
                            "<(module_root_dir)/engine/lib/"
                        ]
                    }
                }
                ],['OS=="linux"',{
                    'cflags_cc!': [
                    '-fno-exceptions'
                    ],'defines': [
                    '__LINUX_ALSASEQ__'
                    ],'link_settings': {
                    'libraries': [
                        '-lal'
                    ]
                    }
                }
                ],['OS=="mac"',{
                    'defines': [
                    '__MACOSX_CORE__'
                    ],'xcode_settings': {
                    'GCC_ENABLE_CPP_EXCEPTIONS': 'YES'
                    },'link_settings': {
                    'libraries': [
                        'OpenAL.framework',],}
                }
                ]
            ]
        }
    ]
}

我已经尝试执行 node-gyp clean.\node_modules\.bin\electron-rebuildnode-gyp configurenode-gyp build 并为 .lib 和 .dll 文件>OpenALsdnFilePortMidi。 我还尝试使用 Pt_Start()Pt_Stop() 而不是为 process_midi 函数创建我自己的线程,但它没有改变任何东西。

我检查了 portmidi.c文件,似乎第 733 行导致了问题,但我有点迷茫......

/* open system dependent input device */
err = (*midi->dictionary->open)(midi,inputDriverInfo);

我使用的是 Windows 10 专业版

  • node-gyp v8.1.0
  • 电子 v13.1.2
  • 节点 v14.16.0

c++ 插件sndFileOpenAL 一起工作正常,但只有 PortMidi 不起作用:/

可在此处找到该应用的所有源代码https://github.com/FurWaz/FyneWav

如果有人能给我提示或建议其他用于 MIDI 的 C++ 库,那将非常有帮助 ^^ 谢谢!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。