Kirjoittaja Aihe: Näppäinten lukeminen (Key status monitor)  (Luettu 2980 kertaa)

Tuxer

  • Käyttäjä
  • Viestejä: 657
  • Debian 7.0, Sailfish
    • Profiili
    • opendimension.org
Näppäinten lukeminen (Key status monitor)
« : 13.04.08 - klo:14.26 »
Laitan tämän tänne ohjelmointipuolelle, python skriptistä on siis kyse.

Löysin vihdoin ohjelman jonka pitäisi näyttää näppäinten tilan eli mitä näppäintä on painettu (tarvitsisin tätä Blender-tutoriaaleihin). Ohjelma Key Status Monitor (http://programmer-art.org/projects/keystatus).  Se lukee tapahtumia seuraavista paikoista:
Koodia: [Valitse]
This program requires the Linux input event system to be loaded, and
requires keyboard and mouse event devices. Please specify the location
of the devices on your system below:
"""

# Device locations
KEYBOARD_LOCATION = "/dev/input/event0"
MOUSE_LOCATION   = "/dev/input/event1"

Nyt sitten loppuu vähän taidot ja tiedot kesken. Ubuntusta löytyy seuraavat laitteet input-hakemistosta:

Koodia: [Valitse]
by-id    event0  event2  event4  event6  mouse0
by-path  event1  event3  event5  mice    mouse1

Olen kokeillut kaikkia mutta mikään ei tunnu toimivan (sudon kanssa ajettuna).

Olisiko kellään mitään ideaa?



"Menehän Tonttu Tomera tarkastamaan ollaanko korsuissa kiltisti."
Fingerpori

snifi

  • Vieras
Vs: Näppäinten lukeminen (Key status monitor)
« Vastaus #1 : 13.04.08 - klo:18.10 »
Jotain tällaista voisit kokeilla:
Koodia: [Valitse]
# Device locations
#KEYBOARD_LOCATION = "/dev/input/event0"
#MOUSE_LOCATION     = "/dev/input/event1"
KEYBOARD_LOCATION = "/dev/input/by-id/usb-_USB_Keyboard-event-kbd"
MOUSE_LOCATION = "/dev/input/by-id/usb-0461_USB_Optical_Mouse-event-mouse"

Vaikuttaisi, että Ubuntussa nuo input/event-numerot vaihtuvat satunnaisesti käynnistyksestä toiseen, mutta /by-id kansiosta voit lukea ne toista kautta.

Blenderiä varten joutui tekemään myös joitain muita muutoksia koodiin, mutta en nyt muista mitä ne olivat, varmaan huomaat ne kun kokeilet ohjelmaa.
« Viimeksi muokattu: 13.04.08 - klo:18.15 kirjoittanut snifi »

snifi

  • Vieras
Vs: Näppäinten lukeminen (Key status monitor)
« Vastaus #2 : 13.04.08 - klo:18.24 »
Ehkä se on paras jos postaan tämän koko koodin tähän, niin voit katsoa siitä suoraan. Huomaa ainakin, että rivillä 68 from evdevDas import Device omassa koodissani luetaan DAS-näppäimistönasettelu, joten siinä kohdassa valitse pelkkä from evdev import....

Koodia: [Valitse]
#!/usr/bin/env python

"""
  GTK+ Key Status Monitor
  Monitor the status of your mouse buttons and the alt/ctrl/shift keys
  Jiri Hnidek added support for other keys

  This program requires the Linux input event system to be loaded, and
  requires keyboard and mouse event devices. Please specify the location
  of the devices on your system below:
"""

# Device locations
#KEYBOARD_LOCATION = "/dev/input/event0"
#MOUSE_LOCATION     = "/dev/input/event1"
KEYBOARD_LOCATION = "/dev/input/by-id/usb-_USB_Keyboard-event-kbd"
MOUSE_LOCATION = "/dev/input/by-id/usb-0461_USB_Optical_Mouse-event-mouse"


#Window width and height
WIDTH= 328
HEIGHT= 48

# Update speed (how fast the interface is updated, in milliseconds)
UPDATE_SPEED = 20

# Delay of displaying key-status, total_delay = DELAY * UPDATE_SPEED [ms]
DELAY = 50 # 7
DELAY_SPECIAL = 50 # 3
DELAY_MOUSE = 50 # 5


"""
  Copyright (C) 2005 Daniel G. Taylor <danielgtaylor at gmail dot com>
  Copyright (C) 2005 Jiri Hnidek <jiri dot hnidek at vslib cz>

  Icons were created by

  Copyright (C) 2005 Jakub (jimmac) Steiner <jakub at ximian dot com>

  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.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

  Release History:
    - Version 1: 12 January 2005
      - Initial release.
    - Version 2: 13 March 2005
      - Added support for other keys and some other tweaking
    - Version 3: 13 March 2005
      - Added support for key-status delay, it is useful for
        video capturing
"""

import gtk, gobject

from sys import argv, exit
from evdevDas import Device # Special thanks to Micah Dowty
import time
import datetime

key_images = {
#"KEY_RESERVED":"./png/null.png",
"KEY_ESC":"./png/Esc.png",
"KEY_1":"./png/1.png",
"KEY_2":"./png/2.png",
"KEY_3":"./png/3.png",
"KEY_4":"./png/4.png",
"KEY_5":"./png/5.png",
"KEY_6":"./png/6.png",
"KEY_7":"./png/7.png",
"KEY_8":"./png/8.png",
"KEY_9":"./png/9.png",
"KEY_0":"./png/0.png",
"KEY_MINUS":"./png/dash.png",
"KEY_EQUAL":"./png/equal.png",
"KEY_BACKSPACE":"./png/backspace.png",
"KEY_TAB":"./png/Tab.png",
"KEY_Q":"./png/q.png",
"KEY_W":"./png/w.png",
"KEY_E":"./png/e.png",
"KEY_R":"./png/r.png",
"KEY_T":"./png/t.png",
"KEY_Y":"./png/y.png",
"KEY_U":"./png/u.png",
"KEY_I":"./png/i.png",
"KEY_O":"./png/o.png",
"KEY_P":"./png/p.png",
"KEY_LEFTBRACE":"./png/squarebracket-left.png",
"KEY_RIGHTBRACE":"./png/squarebracket-right.png",
"KEY_ENTER":"./png/enter.png",
"KEY_A":"./png/a.png",
"KEY_S":"./png/s.png",
"KEY_D":"./png/d.png",
"KEY_F":"./png/f.png",
"KEY_G":"./png/g.png",
"KEY_H":"./png/h.png",
"KEY_J":"./png/j.png",
"KEY_K":"./png/k.png",
"KEY_L":"./png/l.png",
"KEY_SEMICOLON":"./png/semicolon.png",
"KEY_APOSTROPHE":"./png/apostrophe.png",
"KEY_GRAVE":"./png/backquote.png",
"KEY_BACKSLASH":"./png/backslash.png",
"KEY_Z":"./png/z.png",
"KEY_X":"./png/x.png",
"KEY_C":"./png/c.png",
"KEY_V":"./png/v.png",
"KEY_B":"./png/b.png",
"KEY_N":"./png/n.png",
"KEY_M":"./png/m.png",
"KEY_ARING": "./png/aring.png",
"KEY_ADIAERESIS":"./png/adiaeresis.png",
"KEY_ODIAERESIS": "./png/odiaeresis.png",
"KEY_COMMA":"./png/comma.png",
"KEY_DOT":"./png/dot.png",
"KEY_SLASH":"./png/slash.png",
"KEY_KPASTERISK":"./png/kp_asterix.png",
"KEY_SPACE":"./png/spacebar.png",
"KEY_CAPSLOCK":"./png/capslock.png",
"KEY_F1":"./png/F1.png",
"KEY_F2":"./png/F2.png",
"KEY_F3":"./png/F3.png",
"KEY_F4":"./png/F4.png",
"KEY_F5":"./png/F5.png",
"KEY_F6":"./png/F6.png",
"KEY_F7":"./png/F7.png",
"KEY_F8":"./png/F8.png",
"KEY_F9":"./png/F9.png",
"KEY_F10":"./png/F10.png",
"KEY_NUMLOCK":"./png/numlock.png",
#"KEY_SCROLLLOCK":"./png/null.png",
"KEY_KP7":"./png/kp_7.png",
"KEY_KP8":"./png/kp_8.png",
"KEY_KP9":"./png/kp_9.png",
"KEY_KPMINUS":"./png/kp_minus.png",
"KEY_KP4":"./png/kp_4.png",
"KEY_KP5":"./png/kp_5.png",
"KEY_KP6":"./png/kp_6.png",
"KEY_KPPLUS":"./png/kp_plus.png",
"KEY_KP1":"./png/kp_1.png",
"KEY_KP2":"./png/kp_2.png",
"KEY_KP3":"./png/kp_3.png",
"KEY_KP0":"./png/kp_0.png",
"KEY_KPDOT":"./png/kp_dot.png",
#"KEY_103RD":"./png/null.png",
#"KEY_102ND":"./png/null.png",
"KEY_F11":"./png/F11.png",
"KEY_F12":"./png/F12.png",
"KEY_KPENTER":"./png/kp_enter.png",
"KEY_KPSLASH":"./png/kp_slash.png",
#"KEY_SYSRQ":"./png/null.png",
#"KEY_LINEFEED":"./png/null.png",
"KEY_HOME":"./png/home.png",
"KEY_UP":"./png/up.png",
"KEY_PAGEUP":"./png/pageup.png",
"KEY_LEFT":"./png/left.png",
"KEY_RIGHT":"./png/right.png",
"KEY_END":"./png/end.png",
"KEY_DOWN":"./png/down.png",
"KEY_PAGEDOWN":"./png/pagedown.png",
"KEY_INSERT":"./png/insert.png",
"KEY_DELETE":"./png/del.png",
#"KEY_MACRO":"./png/null.png",
#"KEY_MUTE":"./png/null.png",
#"KEY_VOLUMEDOWN":"./png/null.png",
#"KEY_VOLUMEUP":"./png/null.png",
#"KEY_POWER":"./png/null.png",
#"KEY_KPEQUAL":"./png/null.png",
#"KEY_KPPLUSMINUS":"./png/null.png",
"KEY_LEFTMETA":"./png/penguin.png",  # windows button
#"KEY_RIGHTMETA":"./png/win_right.png",  # windows button
#"KEY_COMPOSE":"./png/win_menu.png",  # windows menu button
"KEY_PAUSE":"./png/pause.png"
}

CtrlImages = ("./png/ctrl-null.png", "./png/ctrl.png")
AltImages = ("./png/alt-null.png", "./png/alt.png")
ShiftImages = ("./png/shift-null.png", "./png/shift.png")


class Image(gtk.Image):
  """ Holds an image that can switch between two states """
  def __init__(self, normal, activated):
    gtk.Image.__init__(self)
    self.set_from_file(normal)
    self.normal = normal
    self.activated = activated
    self.status = 0
    self.delay = -1

  def switch(self, key):
    """ Switch states """
    self.status = key
    if key != "null":
      self.set_from_file(self.activated)
    else:
      self.delay = DELAY_SPECIAL
 
  def isPressed(self):
    return self.status != 0 and self.status != "null"
 
  def key_hide(self):
    self.set_from_file(self.normal)
    self.delay = - 1

class KeyImage(gtk.Image):
  """ Holds an image that can switch between 105 states """
  def __init__(self):
    gtk.Image.__init__(self)
    self.set_from_file("./png/null.png")
    self.hide()
    self.delay = -1
    self.images = {}
    for code_key in key_images.keys():
      self.images[code_key] = key_images[code_key]
    self.status = 0
 
  def switch(self, key):
    """ Switch states """
    self.status = key
    if key != "null":
      self.set_from_file(key_images[key])
      self.show()
    else:
      self.delay = DELAY

  def key_hide(self):
    self.hide()
    self.delay = -1
   
class MouseImage(gtk.Image):
  """ Holds an image that can switch between four mouse states """
  def __init__(self, normal, left, middle, right):
    gtk.Image.__init__(self)
    self.set_from_file(normal)
    self.images = {"normal": normal,
      "BTN_LEFT": left,
      "BTN_MIDDLE": middle,
      "BTN_RIGHT": right}
    self.status = "normal"
    self.toggleRight = 0
    self.toggleLeft = 0
    self.delay = -1

  def switch(self, status):
    """ Switch to the new status, either 'BTN_LEFT' 'BTN_MIDDLE' or 'BTN_RIGHT' """
    self.status = status
    self.set_from_file(self.images[status])
 
  def set_normal(self):
    self.status = "normal"
    self.set_from_file(self.images["normal"])
    self.delay = -1
   
  def setToggle(self, btnDict): # oma
    if btnDict.has_key("BTN_LEFT"):
     self.toggleLeft = btnDict["BTN_LEFT"]
   
    if btnDict.has_key("BTN_RIGHT"):
     self.toggleRight = btnDict["BTN_RIGHT"]
   
  def areBothPressed(self): #oma
    #print "LMB = %i" % self.toggleLeft
    #print "RMB = %i" % self.toggleRight
    #print 20*"="
    return (self.toggleLeft==1) and (self.toggleRight==1)
   
 
class KeyStatusApp:
  def __init__(self, decorated=True, logging="none"):
    # setup devices 
    self.logging = logging
    self.logLastKeys = {1:"", 2:"", 3:"", 4:"", 5:"",6:"", 7:""}
    try:
      self.kb = Device(KEYBOARD_LOCATION)  #keyboard
      self.ms = Device(MOUSE_LOCATION)  #mouse
    except OSError, value:
      # show a dialog with the error
      dialog = gtk.Dialog("Error!", buttons=(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
      dialog.vbox.pack_start(gtk.Label("There was an error:\n\n" + str(value)))
      dialog.show_all()
      dialog.run()
      exit(1)
    # setup GUI
    self.window = gtk.Window()
    self.window.set_title("KeyStatus")
    self.window.set_default_size(WIDTH, HEIGHT)
    self.window.set_resizable(True)
    self.window.set_geometry_hints(None, WIDTH, HEIGHT, WIDTH, HEIGHT, WIDTH, HEIGHT, -1, -1, -1.0, -1.0)
    try:
      if not decorated:
        self.window.set_decorated(False)
    except:
      print "AttributeError: 'gtk.Window' object has no attribute 'set_decorated'"

    try:
      self.window.set_keep_above(True)
    except:
      print "AttributeError: 'gtk.Window' object has no attribute 'set_keep_above'"
   
    self.mouse = MouseImage("./png/mouse.png", "./png/mouse-left.png",
      "./png/mouse-middle.png", "./png/mouse-right.png")
    #self.ctrl = Image("./png/ctrl-null.png", "./png/ctrl.png")
    #self.alt = Image("./png/alt-null.png", "./png/alt.png")
    #self.shift = Image("./png/shift-null.png", "./png/shift.png")
    self.ctrl = Image(CtrlImages[0], CtrlImages[1])
    self.alt = Image(AltImages[0], AltImages[1])
    self.shift = Image(ShiftImages[0], ShiftImages[1])   
    self.key = KeyImage()

    hbox1 = gtk.HBox(False, 0)
    hbox1.pack_start(self.mouse, False, True, 0)
    hbox1.pack_start(self.ctrl, False, True, 0)
    hbox1.pack_start(self.alt, False, True, 0)
    hbox1.pack_start(self.shift, False, True, 0)

    hbox2 = gtk.HBox(False, 0)
    hbox2.pack_start(self.key, False, False, 0)

    hbox = gtk.HBox(False, 0)
    hbox.pack_start(hbox1)
    hbox.pack_start(hbox2)

    self.window.add(hbox)

    self.window.show_all()
    # setup events
    self.window.connect("destroy", self.destroy)
    gobject.timeout_add(UPDATE_SPEED, self.update)
    (self.msx, self.msy) = (0,0)# oma
    (self.msxt, self.msyt) =  (0,0) # oma
    self.i = 1
  def destroy(self, widget, data=None):
    gtk.main_quit()
 
  def on_window_clicked():
    print "click"

  def printToLog(self, ctrlStatus, altStatus, shiftStatus, keystring):
    timestr= time.strftime("%Y-%m-%d %H:%M:%S")
    tuloste =  "%s %s%s%s%s" % (timestr, ctrlStatus*"Ctrl-", altStatus*"Alt-", shiftStatus*"Shift-", keystring)
    # html-alternative:
    kuva_alkaa = "<img src=\""
    kuva_loppuu = "\">"
    CtrlImage1 = kuva_alkaa + CtrlImages[1] + kuva_loppuu
    AltImage1 = kuva_alkaa + AltImages[1] + kuva_loppuu
    ShiftImage1 = kuva_alkaa + ShiftImages[1] + kuva_loppuu
    html_tuloste = ""
    if keystring in key_images:
     kuvaImage1 = kuva_alkaa + key_images[keystring] + kuva_loppuu
     html_tuloste =  "<!-- %s --> %s%s%s%s " % (timestr, ctrlStatus*CtrlImage1, altStatus*AltImage1, shiftStatus*ShiftImage1, kuvaImage1)
    if not (tuloste in self.logLastKeys.values()):
      if self.logging == "loggingtxt":
        # txt-logging
        print tuloste
      if self.logging == "logginghtml":
        # html-alternative:
        print html_tuloste
      # dump fifo:
      self.logLastKeys[7] = self.logLastKeys[6]
      self.logLastKeys[6] = self.logLastKeys[5]
      self.logLastKeys[5] = self.logLastKeys[4]
      self.logLastKeys[4] = self.logLastKeys[3]
      self.logLastKeys[3] = self.logLastKeys[2]
      self.logLastKeys[2] = self.logLastKeys[1]
      self.logLastKeys[1] = tuloste


  def update(self):
    """ Update the GUI with new event data from the keyboard and mouse devices """
    self.ms.buttons = {}
   
    self.kb.poll()
    self.ms.poll()

    # print self.kb.buttons  # debug ... it prints internal button names

    key_num = len(self.kb.buttons)
    if  key_num > 0:
      # The keyboard key status is 1 when pressed, 2 when held, and 0 otherwise
      # Special keys status
      for key in ["KEY_LEFTCTRL", "KEY_RIGHTCTRL"]:
        if key in self.kb.buttons:
          key_num = key_num - 1
          if self.kb.buttons[key] and self.ctrl.status != key:
            self.ctrl.switch(key)
          elif self.kb.buttons[key] == 0 and self.ctrl.status == key:
            self.ctrl.switch("null")
           
      for key in ["KEY_LEFTALT", "KEY_RIGHTALT"]:
        if key in self.kb.buttons:
          key_num = key_num - 1
          if self.kb.buttons[key] and self.alt.status != key:
            self.alt.switch(key)
          elif self.kb.buttons[key] == 0 and self.alt.status == key:
            self.alt.switch("null")
     
      for key in ["KEY_LEFTSHIFT", "KEY_RIGHTSHIFT"]:
        if key in self.kb.buttons:
          key_num = key_num - 1
          if self.kb.buttons[key] and self.shift.status != key:
            self.shift.switch(key)
          elif self.kb.buttons[key] == 0 and self.shift.status == key:
            self.shift.switch("null")

      # Other keys status
      if(key_num > 0):
        for key in key_images.keys():
          if key in self.kb.buttons:
            if self.kb.buttons[key] and self.key.status != key:
              self.key.switch(key)
              if self.logging != "none":
                self.printToLog(self.ctrl.isPressed(), self.alt.isPressed(), self.shift.isPressed(), key)
            elif self.kb.buttons[key] == 0 and self.key.status == key:
              self.key.switch("null")

      # Delay business for special keys
      if self.ctrl.delay > 0:
        self.ctrl.delay = self.ctrl.delay - 1
      else:
        if self.ctrl.delay != -1:
          self.ctrl.key_hide()

      if self.alt.delay > 0:
        self.alt.delay = self.alt.delay - 1
      else:
        if self.alt.delay != -1:
          self.alt.key_hide()

      if self.shift.delay > 0:
        self.shift.delay = self.shift.delay - 1
      else:
        if self.shift.delay != -1:
          self.shift.key_hide()

      # Delay business for common keys
      if self.key.delay > 0:
        self.key.delay = self.key.delay - 1
      else:
        if self.key.delay != -1:
          self.key.key_hide()
    #print self.ms.buttons #
    if len(self.ms.buttons) > 0:
      self.mouse.setToggle(self.ms.buttons)

      # The mouse button status
      for button in ["BTN_LEFT", "BTN_MIDDLE", "BTN_RIGHT"]:
        if button in self.ms.buttons:
          # Blender MMB = LMB + RMB
          if self.ms.buttons[button] and self.mouse.status != button:
            if self.mouse.areBothPressed(): button = "BTN_MIDDLE"
            self.mouse.switch(button)
            #print self.mouse.isBothPressed()
            #print self.ms.buttons
          elif self.ms.buttons[button] == 0 and self.mouse.status != "normal":
            self.mouse.delay = DELAY_MOUSE
   
    # Delay business for mouse buttons
    if self.mouse.delay > 0:
      self.mouse.delay = self.mouse.delay - 1
    else:
      if self.mouse.delay != -1:
        self.mouse.set_normal()

    return True

if __name__ == "__main__":
  # Create a new instance of our application
  decorated = True
  logging = "none"
  if len(argv) > 1:
    for argument in argv:
      if argument == "--no-decorations" or argument == "-d":
        decorated = False
      if argument == "--logging-txt" or argument == "-lt":
        logging = "loggingtxt"
      if argument == "--logging-html" or argument == "-lh":
        logging = "logginghtml"
      if argument == "--help" or argument == "-h":
        print "GTK+ Key Status Monitor"
        print "Monitors the status of keyboard and mouse keys."
        print "Options:"
        print "\t--no-decorations, -d: Do not show window decorations."
        print "\t--logging-txt, -lt: Log keystrokes as text to stdout."
        print "\t--logging-html, -lh: Log keystrokes as html-img-tags to stdout."
        print "\t--help, -h: Show this help message!"
        exit(0)
  App = KeyStatusApp(decorated, logging)
  gtk.main() # Start the GTK main loop


Tuxer

  • Käyttäjä
  • Viestejä: 657
  • Debian 7.0, Sailfish
    • Profiili
    • opendimension.org
Vs: Näppäinten lukeminen (Key status monitor)
« Vastaus #3 : 13.04.08 - klo:19.05 »
Suuret kiitokset!

Sain toimimaan seuraavilla asetuksilla:

Koodia: [Valitse]
KEYBOARD_LOCATION = "/dev/input/by-path/platform-i8042-serio-0-event-kbd"
MOUSE_LOCATION   = "/dev/input/by-id/usb-Logitech_USB-PS.2_Optical_Mouse-event-mouse"

Ilmeisesti geneeristä tapaa saada noita selville ei ole?

Blenderissä tuo minulla toimi ilman muutoksia.
« Viimeksi muokattu: 13.04.08 - klo:19.07 kirjoittanut Ari Häyrinen(tuxer) »
"Menehän Tonttu Tomera tarkastamaan ollaanko korsuissa kiltisti."
Fingerpori

snifi

  • Vieras
Vs: Näppäinten lukeminen (Key status monitor)
« Vastaus #4 : 13.04.08 - klo:19.36 »
Tässä on vielä yksi koodi, jos haluat tehdä itse niitä näppäimistöhattuja siihen:

http://pp.kpnet.fi/jhii/key-status-5-jhii/generate_keys_py.html

Olisiko se ollut Blenderissä MMB eli Middle Mouse Button, jota silloin tällöin käytetään, joka ei näkynyt oikealla tavalla. Tai ehkä se oli jotakin muuta: nuolinäppäimet, tabulaattori, numeronäppäimet?... en muista enää.

Tuxer

  • Käyttäjä
  • Viestejä: 657
  • Debian 7.0, Sailfish
    • Profiili
    • opendimension.org
Vs: Näppäinten lukeminen (Key status monitor)
« Vastaus #5 : 14.04.08 - klo:12.17 »
Ehkä tuon voisi muuttaa toimimaan Cairolla, jolloin noita svg-tiedostoja voisi käyttää suoraan? Sitten saisi myös tuon koon muuttuman ikkunan mukaan.
"Menehän Tonttu Tomera tarkastamaan ollaanko korsuissa kiltisti."
Fingerpori