Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: Custom action: Do something only if shell() exits in success #427

Closed
gwemmie opened this issue Oct 20, 2018 · 12 comments
Closed

Comments

@gwemmie
Copy link

gwemmie commented Oct 20, 2018

I want to be able to use the Guide button on my controllers sometimes, like with PPSSPP, but I don't want to have to deal with that thing Steam does where it can't not enter BPM if the Steam window is focused.

I could set the button to a script that checks if my focused window is Steam, and if so does nothing. But I don't actually know how to make that script send a controller button to my entire desktop, and running a whole separate script file is pretty roundabout for a one-line xdotool poll.

So what if I could do something like this?

shell(bash -c 'WINDOW=$(xdotool getwindowname $(xdotool getactivewindow)); if [ "$WINDOW" = "Steam" ]; then exit 1; else exit 0').onsuccess(button(Keys.BTN_MODE))

Maybe one could even go the whole mile and have a full if-statement by also having .onfailure() or something.

@kozec
Copy link
Owner

kozec commented Oct 21, 2018

I'm afraid something like .onsucess can't really work without some major rewrite. Thing is, what you are typing into custom action is not really python nor anything script-like, there are no returns values or variables. It can recognize only action name (i.e. "shell" or "button") and stuff in parentheses.

Other than that, what you are describing shouldn't be a problem to add, but I'll have to think about way to express it without rewriting too much.

@kozec kozec closed this as completed in f058b7e Dec 14, 2018
@kozec
Copy link
Owner

kozec commented Dec 14, 2018

Ok, I'm not entirely sure I haven't created something crazy that I'll have to remove in next release, but I really like this idea and ended up implementing it like this:

There already is modeshift that allows different actions based on which physical buttons are pressed. Now it's possible to use shell('something') instead of physical button, like this:

mode(
  shell('command'),   button(Keys.KEY_C),
  B,                  OSD('B pressed'),
  button(Keys.KEY_N)
)

When used like this, shell('command') works like another button and whether it's "pressed" is determined by exit code. So, if command exits with code 0, virtual "C" key will be pressed, if it fails and 'B' is pressed, OSD message is displayed and if 'B' is not pressed, that last line is used.

Command have 500ms to finish, otherwise it's killed.

// edit: wording

@gwemmie
Copy link
Author

gwemmie commented Dec 15, 2018

Awesome! I'm slightly confused/unsure on your explanation of that middle line. If the script fails and then you press B on the controller, that OSD happens, while if it fails or runs longer than 500ms, and you don't press anything else on the controller for those 500ms, then you get an N? Is that it?

@kozec
Copy link
Owner

kozec commented Dec 15, 2018

If the script fails and then you press B on the controller, that OSD happens, while if it fails or runs longer than 500ms, and you don't press anything else on the controller for those 500ms, then you get an N? Is that it?

Almost. If the script fails and you already have B pressed on the controller, that OSD happens, ...

That shell('command') works like another button and whether it's "pressed" is determined by exit code. And everything waits (asynchronously) up to 500ms to get that exit code.

@gwemmie
Copy link
Author

gwemmie commented Dec 15, 2018

Ah! Right, I should've remembered how mode shift works.

Did you actually recode the entire execution to be able to asynchronously wait for shell()? That's really impressive! I've had enough Javascript horror stories to know that pain.

@kozec
Copy link
Owner

kozec commented Dec 15, 2018

Not really, I've just added it as exception in "on button" handler and code that's called repeatedly by timer until subprocess returns. It's stupid, but works.

On that note, this will not work with anything but buttons, but you probably wouldn't want SCC to execute forkbomb subprocess for every movement you do over touchpad anyway.

@LinuxJoeUser
Copy link

This. Is. So. COOL! I'm gonna have fun playing with this I think. :)

@gwemmie
Copy link
Author

gwemmie commented Dec 21, 2018

It's definitely doing something, but I can't tell if it's working, or if I'm doing something wrong? I have:

hold(menu('Default.menu',DEFAULT,B,A), mode(
  shell('test [[ "$(xdotool getwindowname $(xdotool getactivewindow))" =~ "Steam" ]]'),menu('Default.menu',DEFAULT,B,A),
  button(Keys.BTN_MODE)
), 0.3)

The behavior I get with the Mode button without using shell('command') is, the Steam window appears as soon as I press the button, and then BPM mode starts if I press it again with Steam focused. The behavior I get with this code I'm trying is pretty much the exact same thing, only I have to press the button a few times in a row within a second (i.e. tap it really fast), usually about 3 times, for the system to even register any sort of button press at all, regardless of whether the Steam window is focused or not (so BPM does still happen).

So it seems like all it's doing is making the Mode button just not work sometimes. I checked and made sure those xdotool commands finish in less than 500ms. They definitely do. I also tried using bash -c, and the if-then format I typed earlier instead of a test. The behavior doesn't change. I'm not sure what else to try.

@kozec
Copy link
Owner

kozec commented Dec 21, 2018

Sorry, but how sure are you that test invocation is OK? I'm getting error message both by bash builtin and by /usr/bin/test:

$ test [[ "$(xdotool getwindowname $(xdotool getactivewindow))" =~ "Terminal" ]]
bash: test: too many arguments
$ /usr/bin/test [[ "$(xdotool getwindowname $(xdotool getactivewindow))" =~ "Terminal" ]]
/usr/bin/test: extra argument ‘Terminal - bash’

Anyway, this looks like it does what you are trying to do:

mode(
  shell('xdotool getwindowname $(xdotool getactivewindow) | grep Steam'), menu('Default.menu',DEFAULT,B,A),
  button(Keys.BTN_MODE)
)

@gwemmie
Copy link
Author

gwemmie commented Dec 21, 2018

Oh, what the hell? I'm getting those errors, too. And yet I can't tell what's wrong with it syntactically? I literally checked the docs before typing it (because I'm actually new to using the test command at all). Other than the fact that it is a use of test, it's no different from countless xdotool-involving if-then statements I use in scripts daily.

But yeah, derp, that revision you did is much cleaner and simpler. I put it in, and now the behavior is even weirder, but even more reproducible, and yet even harder to explain.

So, let's say that X is how many clicks of the button it takes to bring the Steam window up, with all but the final click doing nothing (not bringing up sc-controller's menu). If Steam has just booted up or has just exited BPM, X is 2. Otherwise, X is 1. In other words, if BPM opens when I didn't want it to and I have to close it and then close the Steam window to test more, it then takes 2 clicks to get Steam back up. But if I just close Steam without clicking the button again, it only takes 1 click each time until the next time I enter BPM.

But yes, the main problem is that I can still enter BPM, and it's weird. Now, if the Steam window (which is actually named Steam, even according to xdotool) is already focused, simply tapping the button as quickly as I can brings up BPM and sc-controller's own menu--it somehow triggers success and failure results at the same time. And at that point, X is only 1 every time.

@kozec
Copy link
Owner

kozec commented Dec 22, 2018

You should probably explain what are you trying to achieve here, because it sounds like you are fighting with weirdness of SCC and weirdness of Steam at once :) Is there any reason to send Steam button to Steam if you don't wan't BPM in 1st place?

Anyway, while you are testing, I'd suggest having jstest-gtk or similar tool open on screen, so you can see that buttons on virtual pad are responding as expected. Otherwise we can't be sure if there is bug in in SCC or problem with how Steam is responding.

@gwemmie
Copy link
Author

gwemmie commented Dec 24, 2018

Right, sorry, I should be testing this in a less complex setting.

What's going on is, I want to be able to use the Steam button to bring up Steam's main window, but when that window is then focused, I don't want any form of BPM in my life at all, even if I accidentally press the button again or something. Steam itself has no option for this--it wants all or none.

Using jstest, it appears whatever this is is not Steam's fault. Pressing the mode button once did nothing. Pressing it about 3 times in rapid succession got it stuck in the on (pressed in) position, not physically, but virtually as far as jstest was telling me. From there, I could not get it back on the off position for longer than half a second. I could only get its status to change at all by violently tapping it extremely fast, a completely random amount of times (usually somewhere between 7 and a dozen or so), and then it would revert back to on after being off for a split-second, and not even the exact same length of time each time.

I should emphasize here, the entire time, pressing the button once every few seconds never seems to do anything. Changes in its status only occur when I rapidly spam it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants