# Mouse extension to KMttg on windows systems



## rocket777 (Sep 11, 2013)

For a couple months Ive been testing an extension I built for KMttg that turns a mouse into an extra remote controller for a series 4 or later tivo  although I only know for sure it works with my 4 tuner roamio.

My approach was to use KMttg for all the difficult work, i.e. controlling the Tivo, while programming the new mouse interface in a separate process using a language I'm quite experienced using. Thus I could keep the changes to KMttg as minimal as possible. Here's a description of my extension.

When launched, via a windows .bat file, one sees along with kmttg another window that once right-clicked will go fullscreen and thereafter capture all mouse and keyboard commands. This extension will then forward these commands to kmttg which will send out skip and pause commands to the tivo selected in the remote page of kmttg. Mouse motion is ignored and the pointer always stays in the middle of the window. There is no need to see the screen once activated. This lets you close the lid on a laptop and use the mouse as though it were an rf remote control. One can then watch the tv and ignore the computer.

So, one would first setup kmttg (to select which tivo if more than one), and then activate the second window. I have a spare netbook where I leave it running and just hibernate when Im not using it. It comes up running out of hibernation w/o losing a beat. Just one mouse click to turn the mouse back on.

*Controls and settings*:

There are 2 types of commands, keyboard and mouse. The keyboard commands are used mostly to setup various options, while the mouse is used to control the tivo to skip and pause.

One keyboard command (tab) also invokes tivo navigation  typically mapped to pause. Using a freeware mouse button(s) mapper, this command can be mapped to any of the extra mouse buttons, such as the wheel press button, or any 4th or 5th mouse button available on your particular mouse. See below. One might also use the logitech software for this if using one of their mice.

The mouse wheel is used to skip forward or backward a user settable number of seconds, typically about 4 or 5 seconds per click. Shift wheel skips 1 minute forward or back per click.

The right mouse button can be used as a click (down and up quickly) or as a hold (down and hold > ½ second) function. When clicked, this is a (user configurable) short skip forward, typically 15-30 seconds. When held, it acts like a shift key for skipping by minutes using the wheel.

Fast twirling of the mouse wheel is detected and results in kmttg skipping farther in a single operation rather than doing multiple shorter skips. With shifted wheel twirling, one can move very quickly to any spot in a show.

The left mouse button click is used for a larger skip, typically of the order of 2-3 minutes. This too is user configurable.

*Advanced mouse mapping*:

Most mouse wheels can be pressed to provide a middle button command. However, the windows OS does not normally handle these (OS version dependent). So, to use the extra buttons found on some mice, plus the wheel button, I use a freeware mouse button-mapping program. Then I assign the middle mouse button to invoke the tab key. This program also lets me map the extra buttons I have on one of my mice. It can be found here:

http://www.highrez.co.uk/downloads/XMouseButtonControl.htm

*My usage experience*:

I mostly have been using this for watching football, though it was mostly working during this years World Series. Canceling of mouse pointer movement lets one toss the mouse onto the couch without worrying about loss of focus and thus no need to look at the screen. I then use the mouse to skip over commercials in one click. I find that 2 minutes works for most games (especially baseball), but those that are special (Sunday night football, or some college games that are national) 2:30 or even 3:00 is more usual. If I overshoot, I just roll the wheel to back up a bit.

To skip to the next play in football depends on how fast the offence is operating. In todays game, getting off the next play before the defense can adjust makes a 30 second skip too long of a skip duration. I find that 15 to 20 seconds is about right. One can also use the wheel to go play to play and see a frame every few seconds.

I use the shifted wheel and a few twirls to skip 15 minutes of halftime. If I'm exercising while watching, I can hold down the shift and twirl the wheel using one hand, though it's a bit tricky.

I always watch football with at least an hour or two buffered. When my home team is losing or the game is lopsided, I scroll forward quickly watching the score graphic (and the remaining game time). If a team makes a comeback, I roll back to where I was and watch again with anticipation. This way I never get too frustrated or bored. Besides, who wants to suffer through a bad game! Maybe its because I grew up in Philly where one bad play and everyone gives up on the team.

Two wireless mice brands that I have found handy due to their long range (30 feet) are the gearhead and hype. Both sell at frys for $12 and under. Some of the hype mice have 2 extra buttons on the left side which can be assigned to various uses with the above software. I found a white gearhead on sale for $7 that is easier to find on my dark couch. No need for fancy mice with dpi adjustments, just a smallish light one that feels good when held in the hand.

*Implementation details*:

The extension works by modifying 2 files and rebuilding from source KMttg and connecting a tcl/tk program via a pipeline as follows:

mytclkit8.6.exe mouser.tcl noconsole | javaw -jar kmttg.jar q

Mytclkit8.6.exe is a single file (tcl-kit) implementation of the tcl/tk scripting language, prebuilt with several tcl extensions, such as twapi (for doing special windows system functions). Given a .tcl file it runs it similar to how a jar file is run by javaw.

Mouser.tcl is a tcl/tk program I wrote to take mouse and keyboard commands and send then on to kmttg which then invokes several button click commands on the kmttg remote tab (pause toggle and the 2 skip minutes buttons). My mods take advantage of the more recent kmttg implementation of these buttons that allow for fractional minutes.

The q option to kmttg is a new option that enables the mods in kmttg to respond to data coming in from stdin.

Changes to kmttg:

I changed 2 files in kmttg. My approach does not limit kmttg, i.e. all the other kmttg functions still work as best I can tell. However, when using the mouse extension, it is not expected that some functions would be useful, such as starting jobs etc. It would probably be best to run a separate instance of kmttg for that. Still, I believe my approach does nothing to hamper anything else. Occasionally, I need to use kmttg to set a backdoor, and so I dont need to do anything special; I just temporarily stop the mouse-capturing program from holding focus.

Kmttg.java:

This is the main startup code that contains the code for handling command line options. I added the q option. Also in this code I start a repeating timer that wakes every 50 ms (only if q is specified). This timer code first calls a Java method to poll stdin for data, and if data is ready it then issues a read of a single line from stdin. If stdin is not ready, it dismisses the current timer code callback. I am not a Java expert, and so I did a bit of google-ing for this kind of code and I believe the timer wakes up in a separate thread. This requires a bit of mutex code that I will explain later.

The text coming in is from the mouser.tcl program. I devised a protocol whereby short text commands are interpreted inside the kmttg timer code. These result in a call of the doClick method of the several jump forward and backward skip buttons, or the pause button. doClick simulates a user mouse click on those buttons.

Here is where the mutex comes into play. It appears that doClick is an asynchronous method. I dont know exactly how this works, but I discovered through trial and error that it was possible for my timer code to be running again before the prior call to doClick had finished. Thus I needed to set a flag to let me know if the prior doClick was still active  in which case, the timer is simply dismissed until the flag is reset.

The mouser program provides several different skip ahead/back durations, and so the timer routine modifies the amounts in the text boxes prior to doing a doClick operation and restores them afterwards.

Remotegui.java:

This is the code that contains the jump buttons and the text-fields containing the minutes to move forward or back (now as a floating point number). The change here is to expose (public vs. private) 2 buttons and 3 text fields. This lets the timer code have access to these objects.

One not so clean approach was needed to be able to invoke the pause button. This button does not have a statically declared variable that I could simply make public. Therefore I did a hack whereby during the loop that creates all the remote buttons (that have icons) I test for the pause button and store away a reference to that button in a new public static Jbutton pointer.

The only other modifications to this file involve a mutex flag that surrounds the code which is invoked when a remote button is pushed. This flag is the one tested during each activation of the timer code described above. This flag is set even if the q option is not used, but is otherwise ignored.

Mouser.tcl:

This is a separate tcl/tk program that creates a window which has focus (i.e. all mouse and keyboard commands go to this programs window). In order to use the mouse like one would use a remote control, one normally does not want the mouse pointer to be a factor. If one were to accidentally move the mouse and the pointer left the programs window, then mouse clicks or wheel rotations would not be received by this program.

The workaround to this is to create a window (fullscreen optionally) that captures any mouse movement and then moves the mouse pointer back to the center of the window. This is the one function that I did not know how to do using built in tcl/tk commands. Rather, I use the tcl twapi extension package which lets me move the mouse pointer without creating a recursive mouse event in tcl/tk. I mention this because it is the only thing in the mouse program that is tied to windows OS. But for this one capability, I suspect that the program would work on other systems, such as linux or possibly a mac.

I've built kmttg against code trunks starting at 2760 and recently against the latest 2823 and it has been quite stable. In two months, my tivo has rebooted about 4 or 5 times. Only one time did it reboot while this extension was active, and I don't know if it was the cause. KMttg has not faulted once while in this configuration.

Well, thats it. Thanks for reading.


----------



## jgametest (Oct 31, 2013)

It sounds to me if this could be perfected or added into a beta or next release of KMTTG it could solve the navigation problems within the Opera Browser.


----------



## rocket777 (Sep 11, 2013)

jgametest said:


> It sounds to me if this could be perfected or added into a beta or next release of KMTTG it could solve the navigation problems within the Opera Browser.


I'm not sure I understand, unless you envision using the approach (i.e. the pipeline) with another external program. That is certainly possible. For now, the only kmttg functions that can be accessed are the skip ahead/back and pause.

As to perfecting.... just the process of writing my description has caused me to rethink my mutex issue. I now am thinking that a repeating java timer, might be going off before the previous one has finished. If there are any java experts out there, I wonder how this code could be synchronized properly. This was a code fragment I found which I am using to set up a repeating timer.


```
ActionListener al = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                try{
                       // code to run during this timer
                       // needs to check if the last one has finished and do nothing
                       // this time around if the last one is still going
                }catch(IOException io){
                    io.printStackTrace();
                }
            }
        };




// this code is executed one time only
        Timer tttt = new Timer(1000,al); // Timer(TimeInMilliSeconds, ActionListener) 1000ms = 1s 
        tttt.setInitialDelay(1000);
        tttt.setDelay(50);
        tttt.start();
```


----------

