I am very new to Python and Gizmod, so please bear with me. I do have a programming background though, so things are not *that* bad ;)
I am trying to find a way to give my PowerMate some kind of sensitivity control. I find that I would prefer to spin the knob a bit more before some functions get triggered in my scripts. I remember that this option was possible back in my MS Windows days with the PowerMate control panel, but I just can't seem to recreate it using Python/gizmod.
The way I'm trying to approach it is by defining two variables outside of the onDeviceEvent function. One variable (PM_COUNT) will add abs(Event.Value) to itself until it reaches the value specified by the second variable (PM_STEP). At that point in the code, the actual key event (or mouse event or whatever I wish to run) gets executed and PM_COUNT gets reset to zero.
My problem so far lies with the variable's scope. I need to know where I need to place the variables in order for their values to "stick" (i.e. global or static vars), instead of having the values reassigned every time onDeviceEvent gets executed, which pretty much defeats the purpose of having a counter in the first place. I've been trying for a while to place them in different portions in my code (i.e. outside the onDeviceEvent function, outside of the class definition, etc), but I always get the same error when running the script:
-------------
UnboundLocalError: local variable 'PM_COUNT' referenced before assignment
-------------
I would really appreciate it if someone could help me out with this. I know I'm getting close! I didn't want to clutter this post too much, so I decided not to copy+paste the code here, although I can certainly do so in a separate post if someone's interested.
@Tim Burrell: Is there any chance for an event like this to be included in the next version? I'm thinking something like Gizmo.setTicks([int]) to set the number of Event.Value's ("ticks") before the Gizmo.onTick() event gets triggered... That way I can just catch that event and put my relevant code in there. Seems like a cleaner alternative to my counter approach above. Your thoughts?
Thanks in advance for your help!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Previously there was the function:
- Device.setMinimumTimeBetweenEvents(Seconds)
However, this isn't exactly what you want I think. So I implemented the following:
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I implemented the following:
- PowermateDevice.setRotateSensitivity(TicksPerEvent)
This will change the number of ticks required to generate an event. Note that on each direction change of the dial the timer is reset, as I found this produces a more natural feel to the dial.
- PowermateEvent.ClickTime
This is a float value that reports the duration of the click in seconds. I also added a global variable called POWERMATE_LONG_CLICK so you can simply test:
- if PowermateEvent.ClickTime >= POWERMATE_LONG_CLICK: do some stuff
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
That being said, if you still want to know how to do implement this in the python API properly, here's what I would do:
I'm not sure why your PM_COUNT variable is being referenced before assignment, I'd have to see your code. In Gizmod all of the classes are persistent, and no data gets reset ever.
What you should be doing is adding any necessary variables to the class constructor. Ie:
def __init__(self):
self.Count = 0
Then, in onEvent, just do: self.Count += 1, or whatever.
But, probably what you want is to add a Count variable to every PowerMate device that gets registered, so in GizmoRegistrar.py, look for the section about Powermates in handleDeviceAddition. In there I would simply add a new variable to the device class instance:
self.Device.Count = 0
This is one of the neat things about Python. Since it's a dynamically bound language you can add new variables to objects (class instances) at runtime. Then whenever you want to check for the Powermate's count variable you can just reference PowermateDevice.Count.
Does this make any kind of sense?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
This makes a lot of sense! So much so, in fact, that it makes me wonder about what other goodies Python has in store for me... :)
Thank you so much for your examples as well as the code modifications! This definitely helps me out a lot. I will get the SVN and test it out ASAP. I promise to report back to you in case I find anything that might be worth your while.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I finished building the SVN version. I uninstalled the 3.2 version first.
I am using a modified version of the 210-Powermate-Firefox.py script.
I tried adding the following line inside the function:
------------------------
def onDeviceEvent(self, Event, Gizmo = None):
"""
Called from Base Class' onEvent method.
See GizmodDispatcher.onEvent documention for an explanation of this function
"""
Gizmo.setRotateSensitivity(100) # <--- This is the line I added
------------------------
The parser does not complain at all when I restart gizmod, but it throws this error whenever I spin the knob inside Firefox:
------------------------
AttributeError: 'GizmoPowermate' object has no attribute 'setRotateSensitivity'
------------------------
I also tried adding that line to the constructor function, but I quickly figured out that was wrong, since the Gizmo object is outside of the scope of the function. Any ideas as to what I should try next?
Thanks, BK
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hey sorry about that... update from SVN again -- fixed and actually tested this time :).
The best way of doing this is to add the function call to GizmoRegistrar.py in the handleDeviceAddition function. (So when a powermate is registered with Gizmod the sensitivity is set).
I've actually done this, and it's been put into SVN.
I also added a variable in GizmoDeviceStrings.py called POWERMATE_ROTATE_SENSITIVITY (default value is 1).
So now all you should need to do is change this value in GizmoDeviceStrings.py (try setting it to 5 or 10 or something) and the sensitivity will automatically be changed.
Let me know how you make out!
Tim.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am happy to report that the newest revision (197) works great! I set POWERMATE_ROTATE_SENSITIVITY to 10 and it definitely makes a difference. In fact, I believe 10 is the setting I've been looking for.
I am starting to think that although a global approach for this setting is a good idea, a way to override (fine-tune) the value for certain scripts might work out best. I will think this over a bit more and see if I can work it out from here...
Now for the second part: Button Timeouts! That of course doesn't belong in this thread, so I'm jumping to the other one... :)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hmmm... good call. I can definitely see how some scripts might want different sensitivity settings.
It's not exactly ideal, but there's really no problem with calling Gizmo.setRotateSensitivity in each script's onDeviceEvent method. It's an O(1) operation, so no big deal at all.
Maybe at the top of the script have another POWERMATE_ROTATE_SENSITIVITY variable, for niceness sake.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hello,
I am very new to Python and Gizmod, so please bear with me. I do have a programming background though, so things are not *that* bad ;)
I am trying to find a way to give my PowerMate some kind of sensitivity control. I find that I would prefer to spin the knob a bit more before some functions get triggered in my scripts. I remember that this option was possible back in my MS Windows days with the PowerMate control panel, but I just can't seem to recreate it using Python/gizmod.
The way I'm trying to approach it is by defining two variables outside of the onDeviceEvent function. One variable (PM_COUNT) will add abs(Event.Value) to itself until it reaches the value specified by the second variable (PM_STEP). At that point in the code, the actual key event (or mouse event or whatever I wish to run) gets executed and PM_COUNT gets reset to zero.
My problem so far lies with the variable's scope. I need to know where I need to place the variables in order for their values to "stick" (i.e. global or static vars), instead of having the values reassigned every time onDeviceEvent gets executed, which pretty much defeats the purpose of having a counter in the first place. I've been trying for a while to place them in different portions in my code (i.e. outside the onDeviceEvent function, outside of the class definition, etc), but I always get the same error when running the script:
-------------
UnboundLocalError: local variable 'PM_COUNT' referenced before assignment
-------------
I would really appreciate it if someone could help me out with this. I know I'm getting close! I didn't want to clutter this post too much, so I decided not to copy+paste the code here, although I can certainly do so in a separate post if someone's interested.
@Tim Burrell: Is there any chance for an event like this to be included in the next version? I'm thinking something like Gizmo.setTicks([int]) to set the number of Event.Value's ("ticks") before the Gizmo.onTick() event gets triggered... That way I can just catch that event and put my relevant code in there. Seems like a cleaner alternative to my counter approach above. Your thoughts?
Thanks in advance for your help!
Hey Bernardo,
Thanks for your post! And nice to hear about what you're trying to do with Gizmod!
First of all, I quickly added the desired functionality to Gizmod in SVN. If you want to build from SVN check out the wiki: http://gizmod.wiki.sourceforge.net/Compile+from+SVN
Previously there was the function:
- Device.setMinimumTimeBetweenEvents(Seconds)
However, this isn't exactly what you want I think. So I implemented the following:
Oops... wrong button :)
I implemented the following:
- PowermateDevice.setRotateSensitivity(TicksPerEvent)
This will change the number of ticks required to generate an event. Note that on each direction change of the dial the timer is reset, as I found this produces a more natural feel to the dial.
- PowermateEvent.ClickTime
This is a float value that reports the duration of the click in seconds. I also added a global variable called POWERMATE_LONG_CLICK so you can simply test:
- if PowermateEvent.ClickTime >= POWERMATE_LONG_CLICK: do some stuff
That being said, if you still want to know how to do implement this in the python API properly, here's what I would do:
I'm not sure why your PM_COUNT variable is being referenced before assignment, I'd have to see your code. In Gizmod all of the classes are persistent, and no data gets reset ever.
What you should be doing is adding any necessary variables to the class constructor. Ie:
def __init__(self):
self.Count = 0
Then, in onEvent, just do: self.Count += 1, or whatever.
But, probably what you want is to add a Count variable to every PowerMate device that gets registered, so in GizmoRegistrar.py, look for the section about Powermates in handleDeviceAddition. In there I would simply add a new variable to the device class instance:
self.Device.Count = 0
This is one of the neat things about Python. Since it's a dynamically bound language you can add new variables to objects (class instances) at runtime. Then whenever you want to check for the Powermate's count variable you can just reference PowermateDevice.Count.
Does this make any kind of sense?
This makes a lot of sense! So much so, in fact, that it makes me wonder about what other goodies Python has in store for me... :)
Thank you so much for your examples as well as the code modifications! This definitely helps me out a lot. I will get the SVN and test it out ASAP. I promise to report back to you in case I find anything that might be worth your while.
I finished building the SVN version. I uninstalled the 3.2 version first.
I am using a modified version of the 210-Powermate-Firefox.py script.
I tried adding the following line inside the function:
------------------------
def onDeviceEvent(self, Event, Gizmo = None):
"""
Called from Base Class' onEvent method.
See GizmodDispatcher.onEvent documention for an explanation of this function
"""
Gizmo.setRotateSensitivity(100) # <--- This is the line I added
------------------------
The parser does not complain at all when I restart gizmod, but it throws this error whenever I spin the knob inside Firefox:
------------------------
AttributeError: 'GizmoPowermate' object has no attribute 'setRotateSensitivity'
------------------------
I also tried adding that line to the constructor function, but I quickly figured out that was wrong, since the Gizmo object is outside of the scope of the function. Any ideas as to what I should try next?
Thanks, BK
Hey sorry about that... update from SVN again -- fixed and actually tested this time :).
The best way of doing this is to add the function call to GizmoRegistrar.py in the handleDeviceAddition function. (So when a powermate is registered with Gizmod the sensitivity is set).
I've actually done this, and it's been put into SVN.
I also added a variable in GizmoDeviceStrings.py called POWERMATE_ROTATE_SENSITIVITY (default value is 1).
So now all you should need to do is change this value in GizmoDeviceStrings.py (try setting it to 5 or 10 or something) and the sensitivity will automatically be changed.
Let me know how you make out!
Tim.
I am happy to report that the newest revision (197) works great! I set POWERMATE_ROTATE_SENSITIVITY to 10 and it definitely makes a difference. In fact, I believe 10 is the setting I've been looking for.
I am starting to think that although a global approach for this setting is a good idea, a way to override (fine-tune) the value for certain scripts might work out best. I will think this over a bit more and see if I can work it out from here...
Now for the second part: Button Timeouts! That of course doesn't belong in this thread, so I'm jumping to the other one... :)
Hmmm... good call. I can definitely see how some scripts might want different sensitivity settings.
It's not exactly ideal, but there's really no problem with calling Gizmo.setRotateSensitivity in each script's onDeviceEvent method. It's an O(1) operation, so no big deal at all.
Maybe at the top of the script have another POWERMATE_ROTATE_SENSITIVITY variable, for niceness sake.