diff -u --recursive ./pristine/gizmod-2.2/config/gizmoDaemonConfig.py ./gizmod-2.2/config/gizmoDaemonConfig.py --- ./pristine/gizmod-2.2/config/gizmoDaemonConfig.py 2006-03-24 14:09:50.000000000 -0500 +++ ./gizmod-2.2/config/gizmoDaemonConfig.py 2006-03-26 13:31:19.000000000 -0500 @@ -79,7 +79,12 @@ # load powermate plugin print " Loading Griffin PowerMate Plugin..." self.powermates = 0 - while GizmoDaemon.loadPlugin("GizmoPluginPowerMate", "auto") != -1: + while True: + DeviceID = GizmoDaemon.loadPlugin("GizmoPluginPowerMate", "auto"); + if DeviceID == -1: + break + print "----- powermate ", DeviceID + GizmoDaemon.genericSetGrabExclusiveAccess( DeviceID, True ) self.powermates += 1 # load alsa mixer plugin @@ -174,6 +179,9 @@ # Event Handlers ##### + def onPowerMateShuttle( self, DeviceID, Value ): + debugPrint( "GizmoScript :: OnPowerMateShuttle [" + str(Value) + "]" ) + def onPowerMateRotate(self, DeviceID, Value, ButtonPressed, DevicePath): debugPrint("GizmoScript :: OnPowerMateRotate [" + str(DeviceID) + "] [" + DevicePath + "] [Btn = " + str(ButtonPressed) + "] == " + str(Value)) @@ -216,18 +224,18 @@ ##################### - def onPowerMatePress(self, DeviceID, DevicePath): - debugPrint("GizmoScript :: OnPowerMatePress [" + str(DeviceID) + "] [" + DevicePath + "]") + def onPowerMatePress(self, DeviceID, DevicePath, ButtonID): + debugPrint("GizmoScript :: OnPowerMatePress [" + str(DeviceID) + "] [" + DevicePath + "] [" + str(ButtonID) + "]") ##################### - def onPowerMateRelease(self, DeviceID, DevicePath): - debugPrint("GizmoScript :: OnPowerMateRelease [" + str(DeviceID) + "] [" + DevicePath + "]") + def onPowerMateRelease(self, DeviceID, DevicePath, ButtonID): + debugPrint("GizmoScript :: OnPowerMateRelease [" + str(DeviceID) + "] [" + DevicePath + "] [" + str(ButtonID) + "]") ##################### - def onPowerMateClick(self, DeviceID, DevicePath): - debugPrint("GizmoScript :: OnPowerMateClick [" + str(DeviceID) + "] [" + DevicePath + "]") + def onPowerMateClick(self, DeviceID, DevicePath, ButtonID): + debugPrint("GizmoScript :: OnPowerMateClick [" + str(DeviceID) + "] [" + DevicePath + "] [" + str(ButtonID) + "]") if self.Ctrl: self.selectMonitorNext() @@ -285,7 +293,8 @@ self.onX10Press(DeviceID, ButtonCode, ButtonString, DevicePath) return - debugPrint("GizmoScript :: onGenericPress [" + str(ButtonCode) + "] [" + DeviceName + "] -- " + ButtonString + " <" + str(DeviceID) + ">") + if (DeviceName != "PS/2 Generic Mouse") and (DeviceName != "AT Translated Set 2 keyboard"): + debugPrint("GizmoScript :: onGenericPress [" + str(ButtonCode) + "] [" + DeviceName + "] -- " + ButtonString + " <" + str(DeviceID) + ">") if string.find(DeviceName, DEVICE_KEYBOARD) != -1: if ButtonString == "KEY_LEFTCTRL" or ButtonString == "KEY_RIGHTCTRL": @@ -305,7 +314,8 @@ self.onX10Release(DeviceID, ButtonCode, ButtonString, DevicePath) return - debugPrint("GizmoScript :: onGenericRelease [" + str(ButtonCode) + "] [" + DeviceName + "] -- " + ButtonString + " <" + str(DeviceID) + ">") + if (DeviceName != "PS/2 Generic Mouse") and (DeviceName != "AT Translated Set 2 keyboard"): + debugPrint("GizmoScript :: onGenericRelease [" + str(ButtonCode) + "] [" + DeviceName + "] -- " + ButtonString + " <" + str(DeviceID) + ">") if string.find(DeviceName, DEVICE_KEYBOARD) != -1: if ButtonString == "KEY_LEFTCTRL" or ButtonString == "KEY_RIGHTCTRL": @@ -321,7 +331,8 @@ ##################### def onGenericClick(self, DeviceID, ButtonCode, ButtonString, DeviceName, DevicePath): - debugPrint("GizmoScript :: onGenericClick [" + str(ButtonCode) + "] [" + DeviceName + "] -- " + ButtonString + " <" + str(DeviceID) + ">") + if (DeviceName != "PS/2 Generic Mouse") and (DeviceName != "AT Translated Set 2 keyboard"): + debugPrint("GizmoScript :: onGenericClick [" + str(ButtonCode) + "] [" + DeviceName + "] -- " + ButtonString + " <" + str(DeviceID) + ">") if string.find(DeviceName, DEVICE_ATIX10) != -1: self.onX10Click(DeviceID, ButtonCode, ButtonString, DevicePath) @@ -437,7 +448,8 @@ self.onX10Relative(DeviceID, Axis, Value, DevicePath) return - debugPrint("GizmoScript :: onGenericRelative [" + str(Axis) + "] [" + str(Value) + "] <" + DeviceName + " -- " + DevicePath + "> <" + str(DeviceID) + ">") + if (DeviceName != "PS/2 Generic Mouse") and (DeviceName != "AT Translated Set 2 keyboard"): + debugPrint("GizmoScript :: onGenericRelative [" + str(Axis) + "] [" + str(Value) + "] <" + DeviceName + " -- " + DevicePath + "> <" + str(DeviceID) + ">") ##################### @@ -447,7 +459,8 @@ ##################### def onGenericMisc(self, DeviceID, Axis, Value, DeviceName, DevicePath): - debugPrint("GizmoScript :: onGenericMisc [" + str(Axis) + "] [" + str(Value) + "] <" + DeviceName + " -- " + DevicePath + "> <" + str(DeviceID) + ">") + if (DeviceName != "PS/2 Generic Mouse") and (DeviceName != "AT Translated Set 2 keyboard"): + debugPrint("GizmoScript :: onGenericMisc [" + str(Axis) + "] [" + str(Value) + "] <" + DeviceName + " -- " + DevicePath + "> <" + str(DeviceID) + ">") ##################### @@ -1244,17 +1257,22 @@ # Event Handlers ################### -def onPowerMateRotate(DeviceID, Value, ButtonPressed, DevicePath): - GizmoScript.onPowerMateRotate(DeviceID, Value, ButtonPressed, DevicePath) +def onPowerMateRotate(DeviceID, Value, ButtonPressed, DevicePath, WheelID): + # Differentiate between the jog wheel and shuttle + if( WheelID == 0 ): + GizmoScript.onPowerMateRotate(DeviceID, Value, ButtonPressed, DevicePath) + else: + GizmoScript.onPowerMateShuttle(DeviceID, Value) + -def onPowerMatePress(DeviceID, DevicePath): - GizmoScript.onPowerMatePress(DeviceID, DevicePath) +def onPowerMatePress(DeviceID, DevicePath, ButtonID): + GizmoScript.onPowerMatePress(DeviceID, DevicePath, ButtonID) -def onPowerMateRelease(DeviceID, DevicePath): - GizmoScript.onPowerMateRelease(DeviceID, DevicePath) +def onPowerMateRelease(DeviceID, DevicePath, ButtonID): + GizmoScript.onPowerMateRelease(DeviceID, DevicePath, ButtonID) -def onPowerMateClick(DeviceID, DevicePath): - GizmoScript.onPowerMateClick(DeviceID, DevicePath) +def onPowerMateClick(DeviceID, DevicePath, ButtonID): + GizmoScript.onPowerMateClick(DeviceID, DevicePath, ButtonID) def onPowerMateLEDChange(DeviceID, Value, ButtonPressed, DevicePath): GizmoScript.onPowerMateLEDChange(DeviceID, Value, ButtonPressed, DevicePath) diff -u --recursive ./pristine/gizmod-2.2/plugins/powermate/GizmoPluginPowerMate.cpp ./gizmod-2.2/plugins/powermate/GizmoPluginPowerMate.cpp --- ./pristine/gizmod-2.2/plugins/powermate/GizmoPluginPowerMate.cpp 2006-03-24 14:09:52.000000000 -0500 +++ ./gizmod-2.2/plugins/powermate/GizmoPluginPowerMate.cpp 2006-03-26 14:02:55.000000000 -0500 @@ -45,14 +45,18 @@ /////////////////////////////////////// #define DEVICE_OPENMODE O_RDWR -#define NUM_VALID_PREFIXES 2 +#define NUM_VALID_PREFIXES 3 #define NUM_EVENT_DEVICES 16 #define IBUF_SIZE 32 #define NUM_BLINKS 7 +#define CONTOUR_SHUTTLE_WHEEL 8 +#define CONTOUR_SHUTTLE_JOG 7 + static const char * valid_prefix[NUM_VALID_PREFIXES] = { "Griffin PowerMate\0", - "Griffin SoundKnob\0" + "Griffin SoundKnob\0", + "Contour Design ShuttlePRO v2", }; int GizmoPluginPowerMate::m_TotalFound = 1; @@ -68,21 +72,66 @@ } void GizmoPluginPowerMate::onInputRelative(int Code, int Value) { - Debug::outDebug("GizmoPluginPowerMate[%s] :: onPowerMateRotate: [%d] [%d] Btn = [%d]", m_DevicePath.getString(), Code, Value, m_Button); + Debug::outDebug("GizmoPluginPowerMate[%s] :: onPowerMateRotate: [%d] [%d] Btn = [0x%04x]", m_DevicePath.getString(), Code, Value, m_Button); - // keep track of turn and press separately - if (m_Button) - m_Turned = true; + // The ShuttlePro has multiple buttons and two wheels, + // so we must track them separately. Since the Powermate + // only has one of each, it is a degenerate case. + + // For the ShuttlePro, the jog dial is code 7 and the shuttle is 8 + // We treat the jog the same as the Powermate, while the shuttle is + // more like a scroll wheel + // + // Another broken feature of the ShuttlePro is that the Linux HID + // driver does NOT output a 0 value for the wheel in the center. + // Instead, we have a heuristic that if we receive a JOG event + // with out having received a shuttle event in the past few ms + // then we assume that the wheel has been centered. + const unsigned long now = UtilTime::getTicks(); + const unsigned long shuttle_delta = now - m_ShuttleLast; + + if( Code == CONTOUR_SHUTTLE_JOG ) + { + if( shuttle_delta > 5000 && m_ShuttleSynth ) + { + // We're back in the center and need a synthetic event. + // Make a synthetic event + Code = CONTOUR_SHUTTLE_WHEEL; + Value = 0; + m_ShuttleLast = now; + m_ShuttleSynth = 0; + } else { + // Check to see if we have change the jog dial + if( m_RotLast == Value ) + return; + + // Translate the position into a rotational rate + const int rate = Value - m_RotLast; + m_RotLast = Value; + Value = rate; + } + } else + if( Code == CONTOUR_SHUTTLE_WHEEL ) + { + // Don't do any sensitivity checks for the shuttle wheel + m_ShuttleLast = now; + m_ShuttleSynth = 1; + } else + { + // PowerMate + if (m_Button) + m_Turned = true; - // do sensitivity - if (m_RotLast != Value) { - m_RotLast = Value; - m_RotCount = 0; - } else { - if (++m_RotCount < m_RotSensitivity) - return; - else + // do sensitivity + if (m_RotLast != Value) { + m_RotLast = Value; m_RotCount = 0; + } else { + if (++m_RotCount < m_RotSensitivity) + return; + else + m_RotCount = 0; + } } ScriptFuncArg * pArgDeviceID = m_ScriptFuncOnPowerMateRotate.getInArg(0); @@ -105,24 +154,39 @@ Debug::outDebug("GizmoPluginPowerMate :: Failed to Call OnPowerMateRotate -- Arg 3"); return; } + + ScriptFuncArg * pArgWheelID = m_ScriptFuncOnPowerMateRotate.getInArg(4); + if( !pArgWheelID ) { + Debug::outDebug("GizmoPluginPowerMate :: Failed to Call OnPowerMateRotate -- Arg 4"); + return; + } + pArgDeviceID->ArgNumber = m_DeviceID; pArgValue->ArgNumber = Value; - pArgButtonPressed->ArgBoolean = m_Button; + pArgButtonPressed->ArgNumber = m_Button; pArgDevicePath->ArgString = m_DevicePath; + pArgWheelID->ArgNumber = Code == CONTOUR_SHUTTLE_WHEEL; if (m_pScriptEngine) m_pScriptEngine->callScriptFunction(&m_ScriptFuncOnPowerMateRotate); } void GizmoPluginPowerMate::onInputKey(int Code, int Value) { - if ( (m_Button = Value) ) { + // Turn off the high bit. Why is it set? + Code &= ~( 1 << 7 ); + + if( Value ) + { + m_Button |= 1 << Code; Debug::outDebug("GizmoPluginPowerMate :: onPowerMatePress [%d] [%d]", Code, Value); ScriptFuncArg * pArgDeviceID = m_ScriptFuncOnPowerMatePress.getInArg(0); ScriptFuncArg * pArgDevicePath = m_ScriptFuncOnPowerMatePress.getInArg(1); + ScriptFuncArg * pArgButtonID = m_ScriptFuncOnPowerMatePress.getInArg(2); if (m_pScriptEngine && pArgDeviceID && pArgDevicePath) { pArgDeviceID->ArgNumber = m_DeviceID; pArgDevicePath->ArgString = m_DevicePath; + pArgButtonID->ArgNumber = Code; m_pScriptEngine->callScriptFunction(&m_ScriptFuncOnPowerMatePress); } else { Debug::outDebug("GizmoPluginPowerMate :: Failed to Call Event Function"); @@ -130,12 +194,16 @@ } else { + m_Button &= ~( 1 << Code ); + Debug::outDebug("GizmoPluginPowerMate :: onPowerMateRelease [%d] [%d]", Code, Value); ScriptFuncArg * pArgDeviceID = m_ScriptFuncOnPowerMateRelease.getInArg(0); ScriptFuncArg * pArgDevicePath = m_ScriptFuncOnPowerMateRelease.getInArg(1); + ScriptFuncArg * pArgButtonID = m_ScriptFuncOnPowerMateRelease.getInArg(2); if (m_pScriptEngine && pArgDeviceID && pArgDevicePath) { pArgDeviceID->ArgNumber = m_DeviceID; pArgDevicePath->ArgString = m_DevicePath; + pArgButtonID->ArgNumber = Code; m_pScriptEngine->callScriptFunction(&m_ScriptFuncOnPowerMateRelease); } else { Debug::outDebug("GizmoPluginPowerMate :: Failed to Call Event Function"); @@ -144,9 +212,11 @@ Debug::outDebug("GizmoPluginPowerMate :: onPowerMateClick [%d] [%d]", Code, Value); pArgDeviceID = m_ScriptFuncOnPowerMateClick.getInArg(0); pArgDevicePath = m_ScriptFuncOnPowerMateClick.getInArg(1); + pArgButtonID = m_ScriptFuncOnPowerMateClick.getInArg(2); if (m_pScriptEngine && pArgDeviceID && pArgDevicePath) { pArgDeviceID->ArgNumber = m_DeviceID; pArgDevicePath->ArgString = m_DevicePath; + pArgButtonID->ArgNumber = Code; m_pScriptEngine->callScriptFunction(&m_ScriptFuncOnPowerMateClick); } else { Debug::outDebug("GizmoPluginPowerMate :: Failed to Call Event Function"); @@ -241,6 +311,8 @@ m_BlinkWatching = false; m_PulseAsleep = 1; m_BlackOnClose = true; + m_ShuttleLast = UtilTime::getTicks(); + m_ShuttleSynth = 0; } GizmoPluginPowerMate::~GizmoPluginPowerMate() { @@ -305,6 +377,11 @@ Debug::out("\t- Found [%s] at [%s]", m_DeviceName.getString(), m_DevicePath.getString()); Debug::outDebug("GizmoPluginPowerMate :: PowerMate Input Plugin Initialized."); + + // Get an exclusive access to this device + // ShuttlePro devices look like mice wheels, so X tries to use them + this->grabExclusiveAccess( 1 ); + return true; } diff -u --recursive ./pristine/gizmod-2.2/plugins/powermate/GizmoPluginPowerMate.hpp ./gizmod-2.2/plugins/powermate/GizmoPluginPowerMate.hpp --- ./pristine/gizmod-2.2/plugins/powermate/GizmoPluginPowerMate.hpp 2006-03-24 14:09:52.000000000 -0500 +++ ./gizmod-2.2/plugins/powermate/GizmoPluginPowerMate.hpp 2006-03-26 13:56:37.000000000 -0500 @@ -110,6 +110,8 @@ int m_BlinkWatching; int m_PulseAsleep; bool m_BlackOnClose; + unsigned long m_ShuttleLast; + bool m_ShuttleSynth; ScriptFunctionOnPowerMateRotate m_ScriptFuncOnPowerMateRotate; ScriptFunctionOnPowerMatePress m_ScriptFuncOnPowerMatePress; diff -u --recursive ./pristine/gizmod-2.2/plugins/powermate/ScriptFunctionOnPowerMateClick.cpp ./gizmod-2.2/plugins/powermate/ScriptFunctionOnPowerMateClick.cpp --- ./pristine/gizmod-2.2/plugins/powermate/ScriptFunctionOnPowerMateClick.cpp 2006-03-24 14:09:52.000000000 -0500 +++ ./gizmod-2.2/plugins/powermate/ScriptFunctionOnPowerMateClick.cpp 2006-03-26 12:34:58.000000000 -0500 @@ -66,6 +66,7 @@ addInArg(SCRIPT_ARG_NUMBER); // DeviceID addInArg(SCRIPT_ARG_STRING); // DevicePath + addInArg(SCRIPT_ARG_NUMBER); // ButtonID } ScriptFunctionOnPowerMateClick::~ScriptFunctionOnPowerMateClick() { diff -u --recursive ./pristine/gizmod-2.2/plugins/powermate/ScriptFunctionOnPowerMatePress.cpp ./gizmod-2.2/plugins/powermate/ScriptFunctionOnPowerMatePress.cpp --- ./pristine/gizmod-2.2/plugins/powermate/ScriptFunctionOnPowerMatePress.cpp 2006-03-24 14:09:52.000000000 -0500 +++ ./gizmod-2.2/plugins/powermate/ScriptFunctionOnPowerMatePress.cpp 2006-03-26 12:30:12.000000000 -0500 @@ -66,6 +66,7 @@ addInArg(SCRIPT_ARG_NUMBER); // DeviceID addInArg(SCRIPT_ARG_STRING); // DevicePath + addInArg(SCRIPT_ARG_NUMBER); // ButtonID } ScriptFunctionOnPowerMatePress::~ScriptFunctionOnPowerMatePress() { diff -u --recursive ./pristine/gizmod-2.2/plugins/powermate/ScriptFunctionOnPowerMateRelease.cpp ./gizmod-2.2/plugins/powermate/ScriptFunctionOnPowerMateRelease.cpp --- ./pristine/gizmod-2.2/plugins/powermate/ScriptFunctionOnPowerMateRelease.cpp 2006-03-24 14:09:52.000000000 -0500 +++ ./gizmod-2.2/plugins/powermate/ScriptFunctionOnPowerMateRelease.cpp 2006-03-26 12:35:06.000000000 -0500 @@ -66,6 +66,7 @@ addInArg(SCRIPT_ARG_NUMBER); // DeviceID addInArg(SCRIPT_ARG_STRING); // DevicePath + addInArg(SCRIPT_ARG_NUMBER); // ButtonID } ScriptFunctionOnPowerMateRelease::~ScriptFunctionOnPowerMateRelease() { diff -u --recursive ./pristine/gizmod-2.2/plugins/powermate/ScriptFunctionOnPowerMateRotate.cpp ./gizmod-2.2/plugins/powermate/ScriptFunctionOnPowerMateRotate.cpp --- ./pristine/gizmod-2.2/plugins/powermate/ScriptFunctionOnPowerMateRotate.cpp 2006-03-24 14:09:52.000000000 -0500 +++ ./gizmod-2.2/plugins/powermate/ScriptFunctionOnPowerMateRotate.cpp 2006-03-26 12:54:01.000000000 -0500 @@ -66,8 +66,9 @@ addInArg(SCRIPT_ARG_NUMBER); // DeviceID addInArg(SCRIPT_ARG_NUMBER); // Rotation Value - addInArg(SCRIPT_ARG_BOOLEAN); // Button Pressed + addInArg(SCRIPT_ARG_NUMBER); // Button Pressed mask addInArg(SCRIPT_ARG_STRING); // DevicePath + addInArg(SCRIPT_ARG_NUMBER); // Which wheel (jog=0 or shuttle=1) } ScriptFunctionOnPowerMateRotate::~ScriptFunctionOnPowerMateRotate() {