Code Monkey home page Code Monkey logo

Comments (17)

hawku avatar hawku commented on May 24, 2024 2

@Shoko84 I might also have some time this weekend to do some driver development, so if you need more help, ask away!

from tabletdriver.

hawku avatar hawku commented on May 24, 2024

I was working on that before I posted the driver to Reddit.

To properly implement the feature, you would need to create a new thread that handles keyboard/mouse macros.
All that also needs some user interface changes, commands, testing and problem solving with different tablets.

I've added a second HID device to the Tablet object:
https://github.com/hawku/TabletDriver/blob/master/TabletDriverService/ProcessCommand.cpp#L89

I doesn't have any functionality, but I was planning to use that to read the tablet's HID interface that sends the button and touch states.
Use USBlyzer or other USB capture software to figure out which interface sends the button states.
Some tablets might send the button states on the same interface as pen position.

from tabletdriver.

Shoko84 avatar Shoko84 commented on May 24, 2024

Gotcha' !

Do you mind if you can create a new branch about this particular issue, since we can work on that together + with some other peoples that are interested ? 😄

I've some knowledges with WPF applications so I might start on the GUI interface firstly !

from tabletdriver.

hawku avatar hawku commented on May 24, 2024

@Shoko84 I will create a branch "buttons" after I have committed and pushed latest changes.

from tabletdriver.

Shoko84 avatar Shoko84 commented on May 24, 2024

Perfect, I will get on it soon, thanks !

from tabletdriver.

Shoko84 avatar Shoko84 commented on May 24, 2024

I don't find anything about getting tablet informations (especially the tablet model) from GUI driver, is there anything to catch this somewhere ?

from tabletdriver.

hawku avatar hawku commented on May 24, 2024

Currently the tablet name detection is just a quick'n'dirty hack:
https://github.com/hawku/TabletDriver/blob/master/TabletDriverGUI/MainWindow.xaml.cs#L1339

That code is parsing the tablet name from the TabletDriverService console output.
I need to figure out a better way to transfer the status information between the DriverService and GUI.

I may add a new logging level which is only used in the status information communication, but for now the quick'n'dirty hack will do.

from tabletdriver.

hawku avatar hawku commented on May 24, 2024

@Shoko84 I've added the "buttons" branch.

from tabletdriver.

Shoko84 avatar Shoko84 commented on May 24, 2024

So the GUI part is mostly done in my local work but I'm struggling at triggering virtual keyboard shortcuts (similar to what Wacom drivers have).

I wanted to add this feature to give tablet buttons an useful utility, at least more than just simulate mouse buttons.
Everything I'm trying isn't working as intended so I'm quite sad. I think I will leave this besides for now and work just on mapping tablet buttons with mouse clicks thanks to your second HID first implmentation.

By the way, since I just own a CTL-480, I might need some help about which informations are sent with other devices (if there are now way to emulate devices)

from tabletdriver.

hawku avatar hawku commented on May 24, 2024

@Shoko84 It is possible to create virtual mouse/keyboard actions with this: https://msdn.microsoft.com/en-us/library/windows/desktop/ms646310(v=vs.85).aspx

That function should be run on a separate thread, because i think that it will block until the keyboard action is done.
Normal tablet actions are currently running in this thread:

void RunTabletThread() {
int status;
bool isFirstReport = true;
bool isResent = false;
double x, y;
BYTE buttons;
chrono::high_resolution_clock::time_point timeBegin = chrono::high_resolution_clock::now();
chrono::high_resolution_clock::time_point timeNow = chrono::high_resolution_clock::now();
chrono::high_resolution_clock::time_point timeLast = chrono::high_resolution_clock::now();
//
// Main Loop
//
while(true) {
//
// Read tablet position
//
status = tablet->ReadPosition();
// Position OK
if(status == Tablet::PacketValid) {
isResent = false;
// Position invalid
// Invalid packet id
} else if(status == Tablet::PacketInvalid) {
continue;
// Valid packet but position is not in-range or invalid
} else if(status == Tablet::PacketPositionInvalid) {
if(!isResent && tablet->state.isValid) {
isResent = true;
tablet->state.isValid = false;
} else {
continue;
}
// Reading failed
} else {
LOG_ERROR("Tablet Read Error!\n");
CleanupAndExit(1);
}
//
// Don't send the first report
//
if(isFirstReport) {
isFirstReport = false;
continue;
}
// Raw position
// LOG_INFO("Raw position: x=%-5d y=%-5d\n", tablet->reportData.x, tablet->reportData.y);
// Debug messages
if(tablet->debugEnabled) {
timeNow = chrono::high_resolution_clock::now();
double delta = (timeNow - timeBegin).count() / 1000000.0;
LOG_DEBUG("STATE: %0.3f, %d, %0.3f, %0.3f, %0.3f\n",
delta,
tablet->state.buttons,
tablet->state.x,
tablet->state.y,
tablet->state.pressure
);
//timeLast = chrono::high_resolution_clock::now();
}
// Set output values
if(status == 0) {
buttons = 0;
} else {
buttons = tablet->state.buttons;
}
// Do not write report when filter is enabled
if(!tablet->filter.isEnabled) {
// Relative mode
if(vmulti->mode == VMulti::ModeRelativeMouse) {
x = tablet->state.x;
y = tablet->state.y;
// Map position to virtual screen (values between 0 and 1)
mapper->GetRotatedTabletPosition(&x, &y);
// Create VMulti report
vmulti->CreateReport(buttons, x, y, tablet->state.pressure);
// Write report to VMulti device
vmulti->WriteReport();
// Absolute / Digitizer mode
} else {
// Get x & y from the tablet state
x = tablet->state.x;
y = tablet->state.y;
// Map position to virtual screen (values betweeb 0->1)
mapper->GetScreenPosition(&x, &y);
// Create VMulti report
vmulti->CreateReport(buttons, x, y, tablet->state.pressure);
// Write report to VMulti device
vmulti->WriteReport();
}
}
}
}

Virtual keyboard actions should be executed from a new thread that reads the input from the secondary HID device. Keyboard macros should be stored in the Tablet object and that will also need a console command for setting up those macros.

Currently there isn't any tablet emulation, but I'm planning to make HID and WinUSB device emulators, so it would be possible to test the driver in a virtual machine.

from tabletdriver.

Shoko84 avatar Shoko84 commented on May 24, 2024

Hi back, the GUI part is almost done (except saving shortcuts into the config file, but it's not a hard work tbh) but I have a issue driver-side when getting the new command (TabletMacro)

To be short, the TabletMacro command receive a string like "0,4,47;1,2,4,59" which means that, for the ButtonMap at the index 0, the ASCII keymacro 4 and 47 are pressed (and then released code-side) and keys 2,4 and597 are pressed for the ButtonMap[1]. Also the value into ButtonMap indexes for shortcuts will be a different value to differentiate these (6 iirc)

The thing is here, I do catch the command (goes into else if correctly) but when I try to LOG_INFO the cmd->values array, it looks like the values are corrupted or not correctly initialized. But if it was really the case, then why it does enter in the condition ? 🤔

The else if condition code written is :

...
        //
	// Tablet buttons macro
	//
	else if (cmd->is("TabletMacro")) {
		LOG_INFO("Entering TabletMacro command\n");
		if (!CheckTablet()) return true;
		LOG_INFO("ValueCount: %d\n", cmd->valueCount);

		std::vector<std::string> v;

		for (auto it : cmd->values)
			v.push_back(std::string(it));

		LOG_INFO("Cmd sent: %s\n", Utils::join(v, " "));

		std::vector<std::string> tempSplit = Utils::split(Utils::join(v, " "), ';');
		std::vector<std::vector<std::string>> tabletMacros;

		for (auto &it : tempSplit)
			tabletMacros.push_back(Utils::split(it, ','));

		for (auto &it : tabletMacros)
		{
			for (auto it2 : it)
				LOG_INFO("%s\n", it2);
			LOG_INFO("\n\n");
			//std::vector<int> keysMacro;

			/*std::transform(it.begin() + 1, it.end(), keysMacro.begin(), [](const std::string& value)
			{
				return std::stoi(value);
			});*/
			//tablet->buttonTabletMap[std::stoi(it[0])] = keysMacro;
			//LOG_INFO("Set the macro to the tablet button [%d]\n", std::stoi(it[0]));
		}
	}
...

And here is what it's been written in the console :
https://puu.sh/zMmMd/b6723b86ea.png

I'm a bit confused and stucked, but if I can understand why and how to fix it, it should be almost finished to be sure 😄

I can push my local work either on my fork repository or into the branches branch here if needed !

from tabletdriver.

hawku avatar hawku commented on May 24, 2024

@Shoko84 LOG_INFO uses the snprintf function to format the string and that function doesn't support C++ strings.
You have to use string.c_str() to get the C-style string for the logging commands.

Example:

LOG_INFO(">> %s\n", cmd->line.c_str());

from tabletdriver.

Shoko84 avatar Shoko84 commented on May 24, 2024

Oh fu*k yeah obviously I feel dumb lmao, I will try that thanks

from tabletdriver.

Shoko84 avatar Shoko84 commented on May 24, 2024

Okay so I'll look forward at your changes with HIDDevice, got busy and will have time this week-end, I'm being optimistic to finish that really soon, thanks for your help!

from tabletdriver.

Shoko84 avatar Shoko84 commented on May 24, 2024

My free time is really bad at the moment tbh, I wish I can finish that asap but can't. Will try to give it a look tomorrow / tonight..

If anyone wanna try to work on it, the last version is pushed and available on the buttons branch iirc

from tabletdriver.

hawku avatar hawku commented on May 24, 2024

@Shoko84 No worries. I don't have much of free time either.
I will look in to the button support when I have the time.

from tabletdriver.

hawku avatar hawku commented on May 24, 2024

Button handling was implemented in version 0.2.2

from tabletdriver.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.