Python / PyGame,Ubuntu 12.04 上的 MIDI

Posted

技术标签:

【中文标题】Python / PyGame,Ubuntu 12.04 上的 MIDI【英文标题】:MIDI on Python / PyGame, Ubuntu 12.04 【发布时间】:2013-01-24 04:13:34 【问题描述】:

尝试在 Ubuntu 12.04 上获取 MIDI 接口以与 pygame 一起使用。我知道键盘可以工作,因为它可以控制 vkeybd 并与 OSX 上的 PyGame 一起工作,所以 python 中的 MIDI 存在问题。

$ python -m pygame.examples.midi --list

Traceback (most recent call last):
  File "/usr/lib/python2.7/runpy.py", line 162, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/usr/lib/python2.7/dist-packages/pygame/examples/midi.py", line 820, in <module>
    print_device_info()
  File "/usr/lib/python2.7/dist-packages/pygame/examples/midi.py", line 25, in     print_device_info
    pygame.midi.init()
  File "/usr/lib/python2.7/dist-packages/pygame/midi.py", line 71, in init
    import pygame.pypm
ImportError: /usr/lib/libportmidi.so.0: undefined symbol: snd_seq_event_input_pending

python-pygame 通过包管理器安装,python-pm 也是如此。

有什么想法吗? :)

【问题讨论】:

运行ldd /usr/lib/libportmidi.so.0。它是否显示任何缺少的库? ldd /usr/lib/libportmidi.so.0linux-vdso.so.1 =&gt; (0x00007fffdabff000)libporttime.so.0 =&gt; /usr/lib/libporttime.so.0 (0x00007ff35ac2f000)libc.so.6 =&gt; /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff35a870000)libpthread.so.0 =&gt; /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ff35a652000)/lib64/ld-linux-x86-64.so.2 (0x00007ff35b05e000) 我应该寻找什么? 诸如此类的未定义符号有时可能表示缺少库。看来所有必需的库都已到位,因此这不是您的问题。在我的系统上,snd_seq_event_input_pending 函数存在于/usr/lib/libasound.so.2 文件中,我在您的ldd 列表中没有看到该函数。 libasound2 包安装了吗? libasound 和 libasound2-dev 都已安装。嗯。 【参考方案1】:

虽然这不能完全回答您的问题,但它可以帮助您自己调试问题。

错误是这样的:

ImportError: /usr/lib/libportmidi.so.0: undefined symbol: snd_seq_event_input_pending

undefined symbol 是动态链接器未能找到snd_seq_event_input_pending 函数所需的代码。

在一个示例 32 位 Oneiric 系统上,我们可以这样做来查看 libportmidi.so.0 的一些符号。

nm -DC /usr/lib/libportmidi.so.0 | grep snd_seq_event_input_pending

U snd_seq_event_input_pending

这告诉我们libportmidi 库需要snd_seq_event_input_pending 的代码,但符号未定义。所以libportmidi 要运行,它还必须加载一个包含此函数的附加库。

在 Oneiric 上,我发现这个符号是在 libasound2.so.2 中定义的。

nm -DC /usr/lib/i386-linux-gnu/libasound.so.2 | grep snd_seq_event_input_pending

000a0fa0 T snd_seq_event_input_pending

T 表示函数存在并且在文本(代码)段中。

通常,关联库的链接会自动发生,因为libasound.so.2 应该由libportmidi 引用。在同一个系统上。

ldd /usr/lib/libportmidi.so.0

....
libasound.so.2 => /usr/lib/i386-linux-gnu/libasound.so.2 (0x00e35000)

这表明libmidi 依赖于libasound。在您的 cmets 的 ldd 输出列表中,没有对 libasound 的引用,因此它不会在加载时尝试自动动态链接 libasound.so.2,从而导致您的错误。

可能出现错误的原因有几个:

libportmidi 链接的方式可能会从 Oneiric 更改为 Precise。例如libportmidi 可能会尝试为libasound 找到它自己的依赖项。 (不太可能)。 libportmidi 的打包中存在一个错误,它没有按应有的方式引用 libasound.so.2。这可能是特定于平台的(例如,只有 64 位系统上的错误)。

我建议您尝试找出系统上包含snd_seq_event_input_pending 函数的库,然后向后工作以尝试确定它未与libportmidi 链接的原因。

以下 bash 命令将帮助您找到实现 snd_seq_event_input_pending 的库。如果您没有找到任何东西,则说明您机器上安装的库有问题。

find /lib /usr/lib -name "lib*.so.*" | while read f; do
    if nm -DC "$f" | grep -q 'T snd_seq_event_input_pending'; then
        echo "$f"
    fi
done

【讨论】:

仍在研究这个,不过这是一个很棒的开始。我想这会给我我需要的东西,一旦我在 Ubuntu 中提交了正确的错误,我会回来查看并奖励赏金。【参考方案2】:

我有完全相同的问题(在 Ubuntu 12.04.1 上),使用例如Frescobaldi 中的 MIDI 播放工具(这是一个 Python 应用程序)。这以前可以正常工作,但现在不行了。

这显然是一个错误编译的 portmidi 包,它于 2013 年 1 月 25 日推出,请参阅https://launchpad.net/ubuntu/+source/portmidi/1:200-0ubuntu1.12.04.1。降级到之前的 1:200-0ubuntu1 包解决了我的问题。

我想正确的做法是在https://bugs.launchpad.net/ubuntu/+source/portmidi/+bugs 的 Launchpad 上提交针对 1:200-0ubuntu1.12.04.1 版本的错误报告。如果它没有得到修复,我们可能还会询问 falkTX 他是否愿意在他的 KXStudio PPA 中提供一个工作包。

仅作记录,以下是 ldd 为我系统上的 1:200-0ubuntu1 libportmidi 提供的内容:

linux-vdso.so.1 =>  (0x00007fffe9bff000)
libasound.so.2 => /usr/lib/x86_64-linux-gnu/libasound.so.2 (0x00007f26264cb000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f26262ae000)
libporttime.so.0 => /usr/lib/libporttime.so.0 (0x00007f26260ab000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2625cec000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f26259f0000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f26257eb000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f26255e3000)
/lib64/ld-linux-x86-64.so.2 (0x00007f26269f4000)

还有破1:200-0ubuntu1.12.04.1版本:

linux-vdso.so.1 =>  (0x00007fff9e3ff000)
libporttime.so.0 => /usr/lib/libporttime.so.0 (0x00007fb84ac71000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb84a8b2000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fb84a694000)
/lib64/ld-linux-x86-64.so.2 (0x00007fb84b0af000)

因此,任何没有碰巧在 libasound2 中链接的应用程序都将被冲洗掉。具体来说,Python portmidi 模块似乎就是这种情况。 (至少从 Ubuntu 12.04 开始,gcc 默认使用 --as-needed 链接器标志,这一事实也加剧了这种错误。我敢打赌,Ubuntu 存储库中仍有相当多的包被破坏正因为如此。)

【讨论】:

我已经在bugs.launchpad.net/ubuntu/+source/portmidi/+bug/1110326 提交了错误报告。如果每个受该错误影响的人都在那里“影响我”,它甚至可能会被注意到。 :) 发现并修复了该错误,请参阅bugs.launchpad.net/ubuntu/+source/portmidi/+bug/1110326。目前,我已经在 Launchpad launchpad.net/~dr-graef/+archive/test 上传了一个固定包(请稍等,在撰写本文时,64 位包仍在等待构建)。【参考方案3】:

如果您现在想修复它,您可以签出最新版本的 portmidi 并按如下方式构建库(假设您已签出或解压缩 portmidi 到名为 portmidi 的目录中):

cd portmidi
make -f pm_linux/Makefile 

默认安装不会构建动态版本的库,因此您需要像这样构建一个:

gcc -shared -Wl,-soname,libportmidi.so.0 -o  pm_linux/libportmidi.so.0 pm_common/pmutil.o pm_linux/pmlinuxalsa.o pm_linux/pmlinux.o pm_common/portmidi.o -lasound

然后您可以复制旧库(以防万一),然后将这个新库复制到它的位置:

sudo cp /usr/lib/libportmidi.so.0 /usr/lib/libportmidi.so.0.orig
sudo cp pm_linux/libportmidi.so.0 /usr/lib/libportmidi.so.0

您的应用现在应该可以运行了...

【讨论】:

以上是关于Python / PyGame,Ubuntu 12.04 上的 MIDI的主要内容,如果未能解决你的问题,请参考以下文章

Pygame 已经安装;但是,python终端说“没有名为'pygame'的模块”(Ubuntu 20.04.1)

Pygame 已经安装;但是,python终端说“没有名为'pygame'的模块”(Ubuntu 20.04.1)

在 Ubuntu 上安装 python 模块

如何在Ubuntu16.04中为python3.5安装pygame?

实战用Python+Pygame+Kivy(Buildozer)+Ubuntu开发安卓android手机端apk游戏及踩坑分享

在 ubuntu 20.04LTS 上安装 pygame 的问题