Не получается пищать PC спикером из python
Пытаюсь пищать в linux из скрипта Pyton. Сразу оговорюсь - системная утилита beep отлично пищит - т.е. спикер живой, система о нём знает. делаю по образу и подобию исходника beep.c из пакета busybox но уже на питоне:
#!/usr/bin/python
import os
import fcntl
import time
KIOCSOUND = 0x4B2F
CLOCK_TICK_RATE = 1193180
def beep(hz, len):
fd = os.open("/dev/console", os.O_WRONLY)
try:
fcntl.ioctl(fd, KIOCSOUND, int(CLOCK_TICK_RATE / hz))
try:
time.sleep(len)
finally:
fcntl.ioctl(fd, KIOCSOUND, 0)
finally:
os.close(fd)
if __name__ == '__main__':
beep(440, 0.5)
и получаю ошибку:
fcntl.ioctl(fd, KIOCSOUND, int(CLOCK_TICK_RATE/hz))
OSError: [Errno 25] Not a tty
пока вывернулся - запуская процесс beep. Но это как-то не красиво. Что я делаю не так в питоне?
Ответы (2 шт):
Смотрим файл errno-base.h :
#define ENOTTY 25 /* Not a typewriter */
Т.е. 25-я ошибка - это ENOTTY. Смотрим man ioctl - что это за ошибка:
ENOTTY Указанный запрос не применяется к типу объекта, на который ссылается файловый дескриптор fd.
Это означает, что Ваша ioctl команда KIOCSOUND = 0x4B2F - не применима к данному устройству. Или Вы придумали эту команду, или данная реализация драйвера её не поддерживает.
В итоге всё получилось и заработало. Дело было действительно в /dev/console, а точнее в /dev/tty0. Как посоветовал @Fat-Zer глянул, что делает beep и обнаружил, что он после не удачной попытки с /dev/tty начинает перебирать по маске /dev/tty* и первый же отлично пищит.
У меня решение под конкретную железку, поэтому пока жёсткое указание /dev/tty0 решило проблему.