LINUX.ORG.RU
ФорумTalks

Озвучиватель девайсов…


0

0

Вчера lester_dev создал топик ( http://www.linux.org.ru/view-message.jsp?msgid=3048980 ) где
 опубликовал скрипт с подобным функционалом.

Ковыря пришел к выводу, что есть там кардинальный недостаток из-за
 использования udev: Необходимость настройки от рута, и некоторые
 другие мелкие неприятности в роде чрезжопного добывания инфы о
 девайсах. Кроме того косяк с извлекаемыми устройствами, кроме того
 что там болк-девайс скрипт больше ничего сказать не мог, решения
 сией проблемы пока меня не посетило, но видимо придтся запоминать
 гдето подключеные девайсы.

Итак скрипт на питоне, вместо фестиваля юзает espeak (исключительно
 из-за наличия женского голоса не наводящего на мысли о порнухе), и
 hal:

radws% cat ec.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
###########################################################################
#  Event Commenter                                                        #
# ------------------------------                                          #
# copyright : © 2008 radiofun                                             #
# jabber    : radiofun@jabber.ru                                          #
#                                                                         #
###########################################################################
#                                                                         #
#   This program is free software; you can redistribute it and/or modify  #
#   it under the terms of the GNU General Public License as published by  #
#   the Free Software Foundation; either version 2 of the License, or     #
#   (at your option) any later version.                                   #
#                                                                         #
###########################################################################

import gobject
import threading
import math
import dbus
import dbus.mainloop.glib
import os

class EventCommenter():#threading.Thread):
    def __init__(self):
        #threading.Thread.__init__(self)
        self.__bus = dbus.SystemBus()
        self.__hm = self.__bus.get_object('org.freedesktop.Hal','/org/freedesktop/Hal/Manager')
        self.__hm.connect_to_signal('DeviceAdded', self.deviceAdded)
        self.__hm.connect_to_signal('DeviceRemoved', self.deviceRemoved)
        self.__message = ""

    def deviceAdded(self, devID):
        device = dbus.Interface(self.__bus.get_object("org.freedesktop.Hal", devID),
                                "org.freedesktop.Hal.Device")
        message = self.__prepareComment(device)
        if len(message) > 0:
            message += " is founded."
            self.__say(message);

    def deviceRemoved(self, devID):
        device = dbus.Interface(self.__bus.get_object("org.freedesktop.Hal", devID),
                                "org.freedesktop.Hal.Device")
        message = self.__prepareComment(device)
        if len(message) > 0:
            message += " is removed."
            self.__say(message);

    #prepare device comment!
    def __prepareComment(self, device):
        message = ""
        if device.PropertyExists('info.capabilities'):
            print 'Have capabilites'
            #if "volume"
            if device.QueryCapability('volume'):
                print 'is volume'
                size =self.__getHumanReadableSize(device.GetProperty('volume.size'))
                message += self.__getDeviceName(device) + " volume with size "+ size
            if device.QueryCapability('storage'):
                print 'is storage'
                message += self.__getDeviceName(device) + " storage"
        return message

    # in uint64!
    def __getHumanReadableSize(self, size):
        dim = int(math.log(size, 1024))
        result = {
            0 : lambda x: str(x) + ' bytes',
            1 : lambda x: str(int(x/1024)) + ' kilobytes',
            2 : lambda x: str(int(x/1.048576e6)) + ' megabytes',
            3 : lambda x: str(int(x/1.073741824e9)) + ' gigabytes'
            }[dim](size)
        return result

    def __getDeviceName(self, device):
        if device.PropertyExists('info.product'):
            return device.GetProperty('info.product')
        return "unknown"

    def __say(self, text):
        pipe = os.popen('espeak -ven+f2 -s 150 -a 10','w')
        print text
        pipe.write(text)
        pipe.close()

    def __del__ (self):
        self.__bus.close()


dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

ec = EventCommenter()

mainloop = gobject.MainLoop()
mainloop.run()

Вот что выводит на stdout при вытаскивании и вставке диска сбубунтой:

radws% ./ec.py
ERROR:dbus.proxies:Introspect error on 
:1.4:/org/freedesktop/Hal/devices/volume_label_Kubuntu_KDE4_8_04_i386:
 dbus.exceptions.DBusException: org.freedesktop.Hal.NoSuchDevice: No
 device with id 
/org/freedesktop/Hal/devices/volume_label_Kubuntu_KDE4_8_04_i386
ERROR:dbus.connection:Exception in handler for D-Bus signal:
Traceback (most recent call last):
  File "/var/lib/python-support/python2.5/dbus/connection.py", line
 214, in maybe_handle_message
    self._handler(*args, **kwargs)
  File "./ec.py", line 30, in deviceRemoved
    message = self.__prepareComment(device)
  File "./ec.py", line 38, in __prepareComment
    if device.PropertyExists('info.capabilities'):
  File "/var/lib/python-support/python2.5/dbus/proxies.py", line 68,
 in __call__
    return self._proxy_method(*args, **keywords)
  File "/var/lib/python-support/python2.5/dbus/proxies.py", line
 140, in __call__
    **keywords)
  File "/var/lib/python-support/python2.5/dbus/connection.py", line
 607, in call_blocking
    message, timeout)
DBusException: org.freedesktop.Hal.NoSuchDevice: No device with
 id /org/freedesktop/Hal/devices/volume_label_Kubuntu_KDE4_8_04_i386
Have capabilites
is volume
Kubuntu-KDE4 8.04 i386 volume with size 678 megabytes is founded.


первое исключение связанно с вышеописанной проблемой. Решается
 правкой функции def deviceRemoved(self, devID) или применением
 машины времени, что я сейчас и пытаюсь сделать.
★★☆

т.е. это прога, которая через alsa-lib орет в колонки что мол в меня воткнули мобильный телефон или тостер?

vilfred ☆☆
()

Да, у меня тоже была идея заюзать hal через dbus, но т.к. я с ним не работал, а учить было лень, пришлось искать альтернативные методы. Кстати s/is founded/was found/.

lester_dev ★★★★★
()
Ответ на: комментарий от sabonez

На лиспе со встроенным ИИ, которая будет имитировать жену.

wfrr ★★☆
() автор топика

>вместо фестиваля юзает espeak (исключительно
из-за наличия женского голоса не наводящего на мысли о порнухе)

А можно голосом белки?

ttnl ★★★★★
()
Ответ на: комментарий от lester_dev

Я тож не работал. Итак все косяки поправил:

radws% ./ec.py
Have capabilites
is volume
Kubuntu-KDE4 8.04 i386 volume with size 678 megabytes was found.
Kubuntu-KDE4 8.04 i386 volume with size 678 megabytes was remove.
Have capabilites
Have capabilites
Have capabilites
is storage
DataTraveler 2.0 storage was found.
Have capabilites
is volume
Volume (vfat) volume with size 973 megabytes was found.
Volume (vfat) volume with size 973 megabytes was remove.
DataTraveler 2.0 storage was remove.

radws% cat ec.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
###########################################################################
#  Event Commenter                                                        #
# ------------------------------                                          #
# copyright : © 2008 radiofun                                             #
# jabber    : radiofun@jabber.ru                                          #
#                                                                         #
###########################################################################
#                                                                         #
#   This program is free software; you can redistribute it and/or modify  #
#   it under the terms of the GNU General Public License as published by  #
#   the Free Software Foundation; either version 2 of the License, or     #
#   (at your option) any later version.                                   #
#                                                                         #
###########################################################################

import gobject
import threading
import math
import dbus
import dbus.mainloop.glib
import os

class EventCommenter():#threading.Thread):
    def __init__(self):
        #threading.Thread.__init__(self)
        self.__bus = dbus.SystemBus()
        self.__hm = self.__bus.get_object('org.freedesktop.Hal','/org/freedesktop/Hal/Manager')
        self.__hm.connect_to_signal('DeviceAdded', self.deviceAdded)
        self.__hm.connect_to_signal('DeviceRemoved', self.deviceRemoved)
        self.__connectedDevices = dict();
        self.__message = ""

    def deviceAdded(self, devID):
        device = dbus.Interface(self.__bus.get_object("org.freedesktop.Hal", devID),
                                "org.freedesktop.Hal.Device")
        message = self.__prepareComment(device)
        if len(message) > 0:
            self.__connectedDevices[devID]=message;
            message += " was found."
            self.__say(message);

    def deviceRemoved(self, devID):
        if devID in self.__connectedDevices:
            message = self.__connectedDevices.pop(devID)
            message += " was remove."
            self.__say(message);

    #prepare device comment!
    def __prepareComment(self, device):
        message = ""
        if device.PropertyExists('info.capabilities'):
            print 'Have capabilites'
            #if "volume"
            if device.QueryCapability('volume'):
                print 'is volume'
                size =self.__getHumanReadableSize(device.GetProperty('volume.size'))
                message += self.__getDeviceName(device) + " volume with size "+ size
            if device.QueryCapability('storage'):
                print 'is storage'
                message += self.__getDeviceName(device) + " storage"
        return message

    # in uint64!
    def __getHumanReadableSize(self, size):
        dim = int(math.log(size, 1024))
        result = {
            0 : lambda x: str(x) + ' bytes',
            1 : lambda x: str(int(x/1024)) + ' kilobytes',
            2 : lambda x: str(int(x/1.048576e6)) + ' megabytes',
            3 : lambda x: str(int(x/1.073741824e9)) + ' gigabytes'
            }[dim](size)
        return result

    def __getDeviceName(self, device):
        if device.PropertyExists('info.product'):
            return device.GetProperty('info.product')
        return "unknown"

    def __say(self, text):
        pipe = os.popen('espeak -ven+f2 -s 150 -a 10','w')
        print text
        pipe.write(text)
        pipe.close()

    def __del__ (self):
        self.__bus.close()


dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

ec = EventCommenter()

mainloop = gobject.MainLoop()
mainloop.run()

wfrr ★★☆
() автор топика
Ответ на: комментарий от Drisch

Вот окончательный вариант, больше добавлять нечего:

#!/usr/bin/python
# -*- coding: utf-8 -*-
###########################################################################
# Event Commenter #
# ------------------------------ #
# copyright : © 2008 radiofun #
# jabber : radiofun@jabber.ru #
# #
###########################################################################
# #
# This program is free software; you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation; either version 2 of the License, or #
# (at your option) any later version. #
# #
###########################################################################

import gobject
import threading
import math
import dbus
import dbus.mainloop.glib
import os

class EventCommenter():#threading.Thread):
def __init__(self):
#threading.Thread.__init__(self)
self.__bus = dbus.SystemBus()
self.__hm = self.__bus.get_object('org.freedesktop.Hal','/org/freedesktop/Hal/Manager')
self.__hm.connect_to_signal('DeviceAdded', self.deviceAdded)
self.__hm.connect_to_signal('DeviceRemoved', self.deviceRemoved)
self.__connectedDevices = dict();

def deviceAdded(self, devID):
device = dbus.Interface(self.__bus.get_object("org.freedesktop.Hal", devID),
"org.freedesktop.Hal.Device")
message = self.__prepareComment(device)
if len(message) > 0:
self.__connectedDevices[devID]=message;
message += ", was found."
self.__say(message);

def deviceRemoved(self, devID):
if devID in self.__connectedDevices:
message = self.__connectedDevices.pop(devID)
message += ", was remove."
self.__say(message);

#prepare device comment!
def __prepareComment(self, device):
message = ""
if device.PropertyExists('info.capabilities'):
isCD = device.QueryCapability('volume.disc')
#if "volume"
if device.QueryCapability('volume') and not isCD:
size =self.__getHumanReadableSize(device.GetProperty('volume.size'))
label = device.GetProperty('volume.label')
if len(label) < 1:
label = device.GetProperty('volume.fsversion')
message += label + " volume, with size "+ size
# if CD or dvd
if isCD:
label = ""
if device.GetProperty('volume.disc.has_audio'):
label += " audio "
if device.GetProperty('volume.disc.is_blank'):
label += " empty "
label += device.GetProperty('volume.disc.type') + " "
label += device.GetProperty('volume.label')
message += label + " disk"
#if storage
elif device.QueryCapability('storage'):
message += self.__getDeviceName(device) + " storage"
#это должно быть саммы последним!
elif (device.PropertyExists('linux.subsystem')
and (device.GetProperty('linux.subsystem') == 'usb')) :
category = device.GetProperty('info.category')
devName = self.__getDeviceName(device)
message += devName + " " + category
return message

# in uint64!
def __getHumanReadableSize(self, size):
dim = int(math.log(size, 1024))
result = {
0 : lambda x: str(x) + ' bytes',
1 : lambda x: str(int(x/1024+0.5)) + ' kilobytes',
2 : lambda x: str(int(x/1.048576e6+0.5)) + ' megabytes',
3 : lambda x: str(int(x/1.073741824e9+0.5)) + ' gigabytes'
}[dim](size)
return result

def __getDeviceName(self, device):
result = ""
if device.PropertyExists('info.vendor'):
result = device.GetProperty('info.vendor') + " "
if device.PropertyExists('info.product'):
result += device.GetProperty('info.product')
else:
result += "unknown"
return result

def __say(self, text):
pipe = os.popen('espeak -ven+f2 -s 150 -a 10','w')
print text
pipe.write(text)
pipe.close()

def __del__ (self):
self.__bus.close()


dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

ec = EventCommenter()

mainloop = gobject.MainLoop()
mainloop.run()

добавлено озвучивание подключения любых устройств на усб шину, кроме того разделы и cd\dvd в том числе пустые, исправлено округление.

wfrr ★★☆
() автор топика
Ответ на: комментарий от Drisch

Вот окончательный вариант, больше добавлять нечего:

#!/usr/bin/python
# -*- coding: utf-8 -*-
###########################################################################
#  Event Commenter                                                        #
# ------------------------------                                          #
# copyright : © 2008 radiofun                                             #
# jabber    : radiofun@jabber.ru                                          #
#                                                                         #
###########################################################################
#                                                                         #
#   This program is free software; you can redistribute it and/or modify  #
#   it under the terms of the GNU General Public License as published by  #
#   the Free Software Foundation; either version 2 of the License, or     #
#   (at your option) any later version.                                   #
#                                                                         #
###########################################################################

import gobject
import threading
import math
import dbus
import dbus.mainloop.glib
import os

class EventCommenter():#threading.Thread):
    def __init__(self):
        #threading.Thread.__init__(self)
        self.__bus = dbus.SystemBus()
        self.__hm = self.__bus.get_object('org.freedesktop.Hal','/org/freedesktop/Hal/Manager')
        self.__hm.connect_to_signal('DeviceAdded', self.deviceAdded)
        self.__hm.connect_to_signal('DeviceRemoved', self.deviceRemoved)
        self.__connectedDevices = dict();

    def deviceAdded(self, devID):
        device = dbus.Interface(self.__bus.get_object("org.freedesktop.Hal", devID),
                                "org.freedesktop.Hal.Device")
        message = self.__prepareComment(device)
        if len(message) > 0:
            self.__connectedDevices[devID]=message;
            message += ", was found."
            self.__say(message);

    def deviceRemoved(self, devID):
        if devID in self.__connectedDevices:
            message = self.__connectedDevices.pop(devID)
            message += ", was remove."
            self.__say(message);

    #prepare device comment!
    def __prepareComment(self, device):
        message = ""
        if device.PropertyExists('info.capabilities'):
            isCD = device.QueryCapability('volume.disc')
            #if "volume"
            if device.QueryCapability('volume') and not isCD:
                size =self.__getHumanReadableSize(device.GetProperty('volume.size'))
                label = device.GetProperty('volume.label')
                if len(label) < 1:
                    label = device.GetProperty('volume.fsversion')
                message += label + " volume, with size "+ size
            # if CD or dvd
            if isCD:
                label = ""
                if device.GetProperty('volume.disc.has_audio'):
                    label += " audio "
                if device.GetProperty('volume.disc.is_blank'):
                    label += " empty "
                label += device.GetProperty('volume.disc.type') + " "
                label += device.GetProperty('volume.label')
                message += label + " disk"
            #if storage
            elif device.QueryCapability('storage'):
                message += self.__getDeviceName(device) + " storage"
            #это должно быть саммы последним!
            elif (device.PropertyExists('linux.subsystem')
                    and (device.GetProperty('linux.subsystem') == 'usb')) :
                category = device.GetProperty('info.category')
                devName = self.__getDeviceName(device)
                message += devName + " " + category
        return message

    # in uint64!
    def __getHumanReadableSize(self, size):
        dim = int(math.log(size, 1024))
        result = {
            0 : lambda x: str(x) + ' bytes',
            1 : lambda x: str(int(x/1024+0.5)) + ' kilobytes',
            2 : lambda x: str(int(x/1.048576e6+0.5)) + ' megabytes',
            3 : lambda x: str(int(x/1.073741824e9+0.5)) + ' gigabytes'
            }[dim](size)
        return result

    def __getDeviceName(self, device):
        result = ""
        if device.PropertyExists('info.vendor'):
            result = device.GetProperty('info.vendor') + " "
        if device.PropertyExists('info.product'):
            result += device.GetProperty('info.product')
        else:
            result += "unknown"
        return result

    def __say(self, text):
        pipe = os.popen('espeak -ven+f2 -s 150 -a 10','w')
        print text
        pipe.write(text)
        pipe.close()

    def __del__ (self):
        self.__bus.close()


dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

ec = EventCommenter()

mainloop = gobject.MainLoop()
mainloop.run()

добавлено озвучивание подключения любых устройств на усб шину, кроме того разделы и cd\dvd в том числе пустые, исправлено округление.

ps. что-то предыдущее не удаляется

wfrr ★★☆
() автор топика

Спасибо.

anonymous
()
Ответ на: комментарий от wfrr

Отличная работа, озвучка классная!

Во-первых, есть смысл предложить это команде gnome, в качестве одного из средств для людей с ограниченными возможностями + уникальная фича, которую можно использовать саму по себе.

Второе, имеет смысл добавить локализацию, чтобы говорило на языке, определяемом локалью.

annoynimous ★★★★★
()

У фестиваля есть очень хорошо сделанный русский голос (гораздо лучше микрософт сэма).

Как как можно безболезненей перевести прогу на русский язык и на движок фестиваля?

PolarFox ★★★★★
()
Ответ на: комментарий от PolarFox

Тут пару дней назад на Фестивале уже выкладывали :)

anonymous
()
Ответ на: комментарий от PolarFox

def __say(self, text):
pipe = os.popen('espeak -ven+f2 -s 150 -a 10','w')
print text
pipe.write(text)
pipe.close()

Заменить 'espeak -ven+f2 -s 150 -a 10' на 'festival --tts --language ru_female', но у вас опция language работать не будет, это нужно скрипт один править.

В espeak en - означает язык, в убунте есть и русский, f - значит female, f2 - значит второй голос (их там 4 или 5), -s задает скорость произнесения слов, а -a задает громкость.

Использовать локализацию я не вижу смысла, потому что не русский женский фестиваля не аналогичный espeak не работает удовлетворительно, да и для многих других языков голосов вообще нет, никаких. Да а мужской русский для фестиваля весит 200 метров и не поставляется с дистрами.

wfrr ★★☆
() автор топика
Ответ на: комментарий от wfrr

Кстати, по хорошему, можно прикрутить стандартный вывод скрипта на вход espeak, тогда постоянно запускать его не потребуется.

wfrr ★★☆
() автор топика
Ответ на: комментарий от wfrr

Да а мужской русский для фестиваля весит 200 метров и не поставляется с дистрами.

Ну так я скачал поставил, проверил. Говорит имхо даже реалистичнее, чем еспиковский.

Но вот просто так выход не перенаправишь. Ибо как задать голос при иницилизации я так и не нашёл, а в не интерактивном режиме с фестивалем сложнее управляться.

PolarFox ★★★★★
()
Ответ на: комментарий от PolarFox

В интерактивном режиме просто отправляешь в пайп '(voice_msu_ru_nsh_cg)', для неинтерактивного в файле /usr/share/festival/languages.scm (алярм, это все для убунты) заменяешь

((equal? language 'klingon)
    (language_klingon))

на

((equal? language 'klingon)
    (language_klingon))
((equal? language 'ru_female)
    (language_russian_female))

и

(define (language_castillian_spanish)
"(language_spanish)
Set up language parameters for Castillian Spanish."

  (voice_el_diphone)
  (set! male1 (lambda () (voice_el_diphone)))

  (Parameter.set 'Language 'spanish)
)

на

(define (language_castillian_spanish)
"(language_spanish)
Set up language parameters for Castillian Spanish."

  (voice_el_diphone)
  (set! male1 (lambda () (voice_el_diphone)))

  (Parameter.set 'Language 'spanish)
)

(define (language_russian_female)
"(language_russian_female)
Set up language parameters for Russian."

  (voice_msu_ru_nsh_cg)
)

а потом задешь в командной строке как я писал выше, но это все для женского голоса, для него портебуется конвертация сообщений из юникода в koi8

wfrr ★★☆
() автор топика
Ответ на: комментарий от wfrr

В общем суть такова. Неплохо было бы озвучивать не только storage-девайсы. А то в наличии мобилка, фотик, вебкамера, мышка, джойстик, принтер, блютуз донгл, хотелось бы услышать и их голос. И еще я бы сократил все эти объявы, оно не нужно знать, как называется модель, т.к. там все равно обычно альфанумериковая белиберда, да и размер мне не нужен. Нужно всего лишь обявить, что подключено мышко, подмонтирован такой-то волюм, и т.д. А еще если ключ типа вербозе указать то чтоб объём инфы регулировать легко. Можно грабить корованы...

anonymous
()
Ответ на: комментарий от anonymous

Цытирую:

>добавлено озвучивание подключения любых устройств на усб шину,


мой принтер опознается, больше девайсов втыкаемых в усб у меня немае.

wfrr ★★☆
() автор топика
Ответ на: комментарий от anonymous

неа,не стоит это того, был бы ноут можно было бы его потаскать с энтим скриптом по друзьям и потыкать усб устройствами в него.

wfrr ★★☆
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.