{"id":18029990,"url":"https://github.com/rspeele/mousemeat","last_synced_at":"2025-10-16T18:25:26.265Z","repository":{"id":146006371,"uuid":"58515045","full_name":"rspeele/MouseMeat","owner":"rspeele","description":"A headless program which records raw mouse input to a plain text format.","archived":false,"fork":false,"pushed_at":"2016-06-13T03:11:03.000Z","size":45,"stargazers_count":10,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-23T01:11:49.451Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rspeele.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-05-11T04:48:37.000Z","updated_at":"2024-10-08T14:46:16.000Z","dependencies_parsed_at":null,"dependency_job_id":"f19309a8-4af4-4294-937e-e191eacb6e56","html_url":"https://github.com/rspeele/MouseMeat","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rspeele%2FMouseMeat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rspeele%2FMouseMeat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rspeele%2FMouseMeat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rspeele%2FMouseMeat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rspeele","download_url":"https://codeload.github.com/rspeele/MouseMeat/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245778703,"owners_count":20670682,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-30T09:12:43.343Z","updated_at":"2025-10-16T18:25:26.184Z","avatar_url":"https://github.com/rspeele.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"## MouseMeat\n\nThis is a program which outputs a stream of JSON objects representing:\n* Information about the mice connected to the system\n* Timestamped mouse movement events\n\nIt does this until receiving standard input, then exits.\n\n### Downloading\n\nYou can obtain a compiled binary from the [releases page](https://github.com/rspeele/MouseMeat/releases).\n\n### Output format\n\nMouseMeat outputs one JSON object, representing a single event, per\nline. This was chosen over outputting a JSON list of event objects,\nbecause in other programs it is easier to handle streaming data from\nMouseMeat's redirected standard output when you can simply read the\nstream a line at a time and feed each line into your JSON parser.\n\nEach event has a type field, and an object field with the same name as\nthe value of its type field, which carries type-specific data.\n\nCurrently, there are only two types of event. Here are examples to\nshow the format -- remember though that in practice each event would\nbe formatted on a single line.\n\n#### Device Info\n\nEach mouse device plugged in when MouseMeat starts generates a device\ninfo event. These events are also generated when additional mice are\nplugged in while MouseMeat is running.\n\nThe `deviceId` field is an arbitrary number chosen by MouseMeat to\ncorrelate the device with its movement events within a single log. It\nhas nothing to do with the type of mouse and cannot be correlated\nacross logs!\n\nThe `usbVendorId` and `usbProductId` fields, taken together, usually\nidentify a mouse model, but some manufacturers use the same product ID\nfor multiple models. There is nothing like a serial number that\nidentifies a specific instance of a product.\n\n```json\n{ \"type\": \"deviceInfo\"\n, \"deviceInfo\":\n  { \"deviceId\": 1\n  , \"usbVendorId\": 2\n  , \"usbProductId\": 3\n  , \"driver\": \"An identifier string for the driver this mouse is using\"\n  , \"description\": \"The description of the device according to Windows\"\n  }\n}\n```\n\n#### Move\n\nEach movement reported by a mouse generates a move event. Note that\nthe `us` field corresponds to the microseconds elapsed as of the\nevent, since an undefined epoch. This does not tell you in calendar\ntime when the log was recorded, but can be used to measure the time\nbetween two events in the same log. You should use a 64-bit integer to\nrepresent this field in your application!\n\nThe `dx` and `dy` fields tell you how far the mouse moved in this\nevent on the X and Y axes. A positive value on the X axis means the\nmouse moved to the right. A positive value on the Y axis means the\nmouse moved forward (away from the user).\n\n```json\n{ \"type\": \"move\"\n, \"move\":\n  { \"deviceId\": 1\n  , \"us\": 60000000\n  , \"dx\": -1\n  , \"dy\": 3\n  }\n}\n```\n\n#### Custom events\n\nIf you would like to write a program that processes these logs and\nsaves extra metadata, like computed statistics or info about the mouse\ndriver settings in use, I suggest making up your own event type and\nadding it at the start or end of the event stream rather than creating\na completely new format.\n\nNo built-in MouseMeat event type will ever start with the string\n`\"custom\"`. Therefore, you can safely name your own event types\nsomething like `\"customMyAppMyEventType\"`.\n\n### Project goals\n\n* Accuracy/Precision of data:\n  * The events should not be subject to mouse smoothing or software acceleration from the OS.\n  * Events should be timestamped precisely, with minimal interference from the performance of the program.\n\n* Ease of use from other programs:\n  * The program should have a liberal license allowing worry-free reuse for any purpose.\n  * The program should communicate using only standard input and output.\n  * The output format should be self-explanatory and easy to parse.\n  * The output format should be extensible, with minimal risk of backwards incompatiblity.\n  * The output format should be consistent. There should be no options to customize it.\n  * Incorrect usage should never cause delayed or inaccurate readings.\n  * The program should compile to a single dependency-free binary for easy redistribution.\n\n### How it works\n\nMouseMeat uses the [Windows Raw Input API](https://msdn.microsoft.com/en-us/library/windows/desktop/ms645536(v=vs.85).aspx)\nto read mouse events.\n\nIt runs two threads using standard C++11 threading APIs. Since the\n32-bit MinGW does not currently implement those APIs, I am using\n[mingw-std-threads](https://github.com/meganz/mingw-std-threads) to\nprovide them. Thanks to [Mega Limited](https://github.com/meganz) for\nthat library!\n\nIts main thread creates a hidden window to register for raw input,\noutputs information about the currently attached mice, then loops\nchecking for new mice and movement events.\n\nWhen this thread receives a movement event, it timestamps it to\nmicrosecond precision using\n[QueryPerformanceCounter](https://msdn.microsoft.com/en-us/library/windows/desktop/ms644904(v=vs.85).aspx)\nand pushes it into a buffer.\n\nMeanwhile, an IO thread waits for events to accumulate in the buffer.\nWhen events are available, this thread exchanges the buffer of\naccumulated events with an empty one, then writes the accumulated\nevents as JSON to standard output. Even if this IO thread is very slow\nto write events -- perhaps due to blocking writes to standard output\n-- the main thread can continue to accurately timestamp and buffer\nnewly received events.\n\nThe IO thread also checks for data in standard input and initiates the\nclean shutdown of the program when it is received. This is implemented\nby [_kbhit](https://msdn.microsoft.com/en-us/library/58w7c94c.aspx) if\nstandard input is a console, and by\n[PeekNamedPipe](https://msdn.microsoft.com/en-us/library/windows/desktop/aa365779(v=vs.85).aspx)\notherwise.\n\n### How to build\n\nInstall MinGW using [mingw-get](https://sourceforge.net/projects/mingw/files/latest/download). Then:\n\n        git clone https://github.com/rspeele/MouseMeat.git\n        cd MouseMeat\n        make\n\n### Potential improvements\n\nI am not a C++ programmer by day, nor do I frequently choose it for\nhobby projects. I use it here in order to work directly with the raw\ninput API and avoid the latency of GC pauses. The code quality could\nbe signficantly improved, and I may have made performance or threading\nblunders.\n\nDue to the way standard input is checked, MouseMeat does not behave\nnicely when its standard input is a redirected file. This use case\nmakes no sense whatsoever, but the lack of any handling for it is\nstill a wart.\n\nMouseMeat does not output any information about click events. This\nmight be desirable for click latency tests.\n\nMouseMeat is currently only available for Windows.\nIt should be possible to create a compatible program for Linux by\nreading from `/dev/input/event*`, and using either\n`/sys/bus/usb/devices` or `/proc/bus/input/devices` to obtain other\ndevice metadata. However, this is not a priority.\n\n### License\n\nMouseMeat is released under the MIT license.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frspeele%2Fmousemeat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frspeele%2Fmousemeat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frspeele%2Fmousemeat/lists"}