⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 powermate.py

📁 这是用python语言写的一个数字广播的信号处理工具包。利用它
💻 PY
字号:
#!/usr/bin/env python## Copyright 2005 Free Software Foundation, Inc.# # This file is part of GNU Radio# # GNU Radio 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 3, or (at your option)# any later version.# # GNU Radio 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 GNU Radio; see the file COPYING.  If not, write to# the Free Software Foundation, Inc., 51 Franklin Street,# Boston, MA 02110-1301, USA.# """Handler for Griffin PowerMate, Contour ShuttlePro & ShuttleXpress USB knobsThis is Linux and wxPython specific."""import osimport sysimport structimport exceptionsimport threadingimport wxfrom gnuradio import gruimported_ok = Truetry:    import select    import fcntlexcept ImportError:    imported_ok = False# First a little bit of background:## The Griffin PowerMate has#  * a single knob which rotates#  * a single button (pressing the knob)## The Contour ShuttleXpress (aka SpaceShuttle) has#  * "Jog Wheel"  -- the knob (rotary encoder) on the inside#  * "Shuttle Ring" -- the spring loaded rubber covered ring#  * 5 buttons## The Contour ShuttlePro has#  * "Jog Wheel" -- the knob (rotary encoder) on the inside#  * "Shuttle Ring" -- the spring loaded rubber covered ring#  * 13 buttons## The Contour ShuttlePro V2 has#  *"Jog Wheel" -- the knob (rotary encoder) on the inside#  * "Shuttle Ring" -- the spring loaded rubber covered ring#  * 15 buttons# We remap all the buttons on the devices so that they start at zero.# For the ShuttleXpress the buttons are 0 to 4 (left to right)# For the ShuttlePro, we number the buttons immediately above# the ring 0 to 4 (left to right) so that they match our numbering# on the ShuttleXpress.  The top row is 5, 6, 7, 8.  The first row below# the ring is 9, 10, and the bottom row is 11, 12.# For the ShuttlePro V2, buttons 13 & 14 are to the# left and right of the wheel respectively.# We generate 3 kinds of events:##   button press/release (button_number, press/release)#   knob rotation (relative_clicks)       # typically -1, +1#   shuttle position (absolute_position)  # -7,-6,...,0,...,6,7# ----------------------------------------------------------------# Our ID's for the devices:# Not to be confused with anything related to magic hardware numbers.ID_POWERMATE         = 'powermate'ID_SHUTTLE_XPRESS    = 'shuttle xpress'ID_SHUTTLE_PRO       = 'shuttle pro'ID_SHUTTLE_PRO_V2    = 'shuttle pro v2'# ------------------------------------------------------------------------# format of messages that we read from /dev/input/event*# See /usr/include/linux/input.h for more info##struct input_event {#        struct timeval time; = {long seconds, long microseconds}#        unsigned short type;#        unsigned short code;#        unsigned int value;#};input_event_struct = "@llHHi"input_event_size = struct.calcsize(input_event_struct)# ------------------------------------------------------------------------# input_event types# ------------------------------------------------------------------------IET_SYN		  = 0x00   # aka RESETIET_KEY		  = 0x01   # key or button press/releaseIET_REL		  = 0x02   # relative movement (knob rotation)IET_ABS		  = 0x03   # absolute position (graphics pad, etc)IET_MSC		  = 0x04IET_LED		  = 0x11IET_SND		  = 0x12IET_REP		  = 0x14IET_FF		  = 0x15IET_PWR		  = 0x16IET_FF_STATUS	  = 0x17IET_MAX		  = 0x1f# ------------------------------------------------------------------------# input_event codes (there are a zillion of them, we only define a few)# ------------------------------------------------------------------------# these are valid for IET_KEYIEC_BTN_0	   = 0x100IEC_BTN_1	   = 0x101IEC_BTN_2	   = 0x102IEC_BTN_3	   = 0x103IEC_BTN_4	   = 0x104IEC_BTN_5	   = 0x105IEC_BTN_6	   = 0x106IEC_BTN_7	   = 0x107IEC_BTN_8	   = 0x108IEC_BTN_9	   = 0x109IEC_BTN_10	   = 0x10aIEC_BTN_11	   = 0x10bIEC_BTN_12	   = 0x10cIEC_BTN_13	   = 0x10dIEC_BTN_14	   = 0x10eIEC_BTN_15	   = 0x10f# these are valid for IET_REL (Relative axes)IEC_REL_X	   = 0x00IEC_REL_Y	   = 0x01IEC_REL_Z	   = 0x02IEC_REL_HWHEEL	   = 0x06IEC_REL_DIAL	   = 0x07   # rotating the knobIEC_REL_WHEEL	   = 0x08   # moving the shuttle ringIEC_REL_MISC	   = 0x09IEC_REL_MAX	   = 0x0f# ------------------------------------------------------------------------class powermate(threading.Thread):    """    Interface to Griffin PowerMate and Contour Shuttles    """    def __init__(self, event_receiver=None, filename=None, **kwargs):        self.event_receiver = event_receiver        self.handle = -1        if not imported_ok:            raise exceptions.RuntimeError, 'powermate not supported on this platform'        if filename:            if not self._open_device(filename):                raise exceptions.RuntimeError, 'Unable to find powermate'        else:            ok = False            for d in range(0, 16):                if self._open_device("/dev/input/event%d" % d):                    ok = True                    break            if not ok:                raise exceptions.RuntimeError, 'Unable to find powermate'        threading.Thread.__init__(self, **kwargs)        self.setDaemon (1)        self.keep_running = True        self.start ()            def __del__(self):        self.keep_running = False        if self.handle >= 0:            os.close(self.handle)            self.handle = -1    def _open_device(self, filename):        try:            self.handle = os.open(filename, os.O_RDWR)            if self.handle < 0:                return False            # read event device name            name = fcntl.ioctl(self.handle, gru.hexint(0x80ff4506), chr(0) * 256)            name = name.replace(chr(0), '')            # do we see anything we recognize?            if name == 'Griffin PowerMate' or name == 'Griffin SoundKnob':                self.id = ID_POWERMATE                self.mapper = _powermate_remapper()            elif name == 'CAVS SpaceShuttle A/V' or name == 'Contour Design ShuttleXpress':                self.id = ID_SHUTTLE_XPRESS                self.mapper = _contour_remapper()            elif name == 'Contour Design ShuttlePRO':                self.id = ID_SHUTTLE_PRO                self.mapper = _contour_remapper()            elif name == 'Contour Design ShuttlePRO v2':                self.id = ID_SHUTTLE_PRO_V2                self.mapper = _contour_remapper()            else:                os.close(self.handle)                self.handle = -1                return False            # get exclusive control of the device, using ioctl EVIOCGRAB	    # there may be an issue with this on non x86 platforms and if	    # the _IOW,_IOC,... macros in <asm/ioctl.h> are changed            fcntl.ioctl(self.handle,gru.hexint(0x40044590), 1)            return True        except exceptions.OSError:            return False        def set_event_receiver(self, obj):        self.event_receiver = obj    def set_led_state(self, static_brightness, pulse_speed=0,                      pulse_table=0, pulse_on_sleep=0, pulse_on_wake=0):        """        What do these magic values mean...        """        if self.id != ID_POWERMATE:            return False                static_brightness &= 0xff;        if pulse_speed < 0:            pulse_speed = 0        if pulse_speed > 510:            pulse_speed = 510        if pulse_table < 0:            pulse_table = 0        if pulse_table > 2:            pulse_table = 2        pulse_on_sleep = not not pulse_on_sleep # not not = convert to 0/1        pulse_on_wake  = not not pulse_on_wake        magic = (static_brightness                 | (pulse_speed << 8)                 | (pulse_table << 17)                 | (pulse_on_sleep << 19)                 | (pulse_on_wake << 20))        data = struct.pack(input_event_struct, 0, 0, 0x04, 0x01, magic)        os.write(self.handle, data)        return True    def run (self):        while (self.keep_running):            s = os.read (self.handle, input_event_size)            if not s:                self.keep_running = False                break            raw_input_event = struct.unpack(input_event_struct,s)            sec, usec, type, code, val = self.mapper(raw_input_event)                        if self.event_receiver is None:                continue                        if type == IET_SYN:    # ignore                pass            elif type == IET_MSC:  # ignore (seems to be PowerMate reporting led brightness)                pass                                 elif type == IET_REL and code == IEC_REL_DIAL:                #print "Dial: %d" % (val,)                wx.PostEvent(self.event_receiver, PMRotateEvent(val))            elif type == IET_REL and code == IEC_REL_WHEEL:                #print "Shuttle: %d" % (val,)                wx.PostEvent(self.event_receiver, PMShuttleEvent(val))            elif type == IET_KEY:                #print "Key: Btn%d %d" % (code - IEC_BTN_0, val)                wx.PostEvent(self.event_receiver,                             PMButtonEvent(code - IEC_BTN_0, val))            else:                print "powermate: unrecognized event: type = 0x%x  code = 0x%x  val = %d" % (type, code, val)class _powermate_remapper(object):    def __init__(self):        pass    def __call__(self, event):        """        Notice how nice and simple this is...        """        return eventclass _contour_remapper(object):    def __init__(self):        self.prev = None    def __call__(self, event):        """        ...and how screwed up this is        """        sec, usec, type, code, val = event        if type == IET_REL and code == IEC_REL_WHEEL:            # === Shuttle ring ===            # First off, this really ought to be IET_ABS, not IET_REL!            # They never generate a zero value so you can't            # tell when the shuttle ring is back in the center.            # We kludge around this by calling both -1 and 1 zero.            if val == -1 or val == 1:                return (sec, usec, type, code, 0)            return event        if type == IET_REL and code == IEC_REL_DIAL:            # === Jog knob (rotary encoder) ===            # Dim wits got it wrong again!  This one should return a            # a relative value, e.g., -1, +1.  Instead they return            # a total that runs modulo 256 (almost!).   For some            # reason they count like this 253, 254, 255, 1, 2, 3            if self.prev is None:                  # first time call                self.prev = val                return (sec, usec, IET_SYN, 0, 0)  # will be ignored above            diff = val - self.prev            if diff == 0:                          # sometimes it just sends stuff...                return (sec, usec, IET_SYN, 0, 0)  # will be ignored above            if abs(diff) > 100:      # crossed into the twilight zone                if self.prev > val:  # we've wrapped going forward                    self.prev = val                    return (sec, usec, type, code, +1)                else:                # we've wrapped going backward                    self.prev = val                    return (sec, usec, type, code, -1)            self.prev = val            return (sec, usec, type, code, diff)        if type == IET_KEY:            # remap keys so that all 3 gadgets have buttons 0 to 4 in common            return (sec, usec, type,                     (IEC_BTN_5, IEC_BTN_6, IEC_BTN_7, IEC_BTN_8,                     IEC_BTN_0, IEC_BTN_1, IEC_BTN_2, IEC_BTN_3, IEC_BTN_4,                     IEC_BTN_9,  IEC_BTN_10,                     IEC_BTN_11, IEC_BTN_12,                     IEC_BTN_13, IEC_BTN_14)[code - IEC_BTN_0], val)                    return event# ------------------------------------------------------------------------# new wxPython event classes# ------------------------------------------------------------------------grEVT_POWERMATE_BUTTON  = wx.NewEventType()grEVT_POWERMATE_ROTATE  = wx.NewEventType()grEVT_POWERMATE_SHUTTLE = wx.NewEventType()EVT_POWERMATE_BUTTON = wx.PyEventBinder(grEVT_POWERMATE_BUTTON, 0)EVT_POWERMATE_ROTATE = wx.PyEventBinder(grEVT_POWERMATE_ROTATE, 0)EVT_POWERMATE_SHUTTLE = wx.PyEventBinder(grEVT_POWERMATE_SHUTTLE, 0)class PMButtonEvent(wx.PyEvent):    def __init__(self, button, value):        wx.PyEvent.__init__(self)        self.SetEventType(grEVT_POWERMATE_BUTTON)        self.button = button        self.value = value    def Clone (self):         self.__class__(self.GetId())        class PMRotateEvent(wx.PyEvent):    def __init__(self, delta):        wx.PyEvent.__init__(self)        self.SetEventType (grEVT_POWERMATE_ROTATE)        self.delta = delta    def Clone (self):         self.__class__(self.GetId())class PMShuttleEvent(wx.PyEvent):    def __init__(self, position):        wx.PyEvent.__init__(self)        self.SetEventType (grEVT_POWERMATE_SHUTTLE)        self.position = position    def Clone (self):         self.__class__(self.GetId())        # ------------------------------------------------------------------------#  Example usage# ------------------------------------------------------------------------if __name__ == '__main__':    class Frame(wx.Frame):        def __init__(self,parent=None,id=-1,title='Title',                     pos=wx.DefaultPosition, size=(400,200)):            wx.Frame.__init__(self,parent,id,title,pos,size)            EVT_POWERMATE_BUTTON(self, self.on_button)            EVT_POWERMATE_ROTATE(self, self.on_rotate)            EVT_POWERMATE_SHUTTLE(self, self.on_shuttle)            self.brightness = 128            self.pulse_speed = 0                        try:                self.pm = powermate(self)            except:                sys.stderr.write("Unable to find PowerMate or Contour Shuttle\n")                sys.exit(1)            self.pm.set_led_state(self.brightness, self.pulse_speed)         def on_button(self, evt):            print "Button %d %s" % (evt.button,                                    ("Released", "Pressed")[evt.value])        def on_rotate(self, evt):            print "Rotated %d" % (evt.delta,)            if 0:                new = max(0, min(255, self.brightness + evt.delta))                if new != self.brightness:                    self.brightness = new                    self.pm.set_led_state(self.brightness, self.pulse_speed)                 def on_shuttle(self, evt):            print "Shuttle %d" % (evt.position,)            class App(wx.App):        def OnInit(self):            title='PowerMate Demo'            self.frame = Frame(parent=None,id=-1,title=title)            self.frame.Show()            self.SetTopWindow(self.frame)            return True    app = App()    app.MainLoop ()

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -