Sapd / HeadsetControl

Sidetone and Battery status for Logitech G930, G533, G633, G933 SteelSeries Arctis 7/PRO 2019 and Corsair VOID (Pro) in Linux and MacOSX
GNU General Public License v3.0
1.44k stars 176 forks source link

How to permanently disable the lights/query the state of the lights? #123

Closed seifrox closed 2 years ago

seifrox commented 3 years ago

Hi,

I am currently using a Logitech G733 headset together with Pull Request 121 on Ubuntu.

I am only interested in turning off the LEDs, which works perfectly fine. However, I noticed every time I turn off my headset and turn it on again, the lights are back on. To avoid calling the tool always manually of course I could just call headsetcontrol -l 0 every couple of seconds/minutes. Is there a possibility to have a more "elegant" solution (am I missing something?)

Could i check the status of the lights or even better somehow recognize that the headset was turned on, to trigger sending the LEDs off command?

BR, Alex

Sapd commented 3 years ago

So the application is written in a quite simple way. It does not act as a daemon, and as such it can't actually recognise, when something is plugged in. (Although I thought about introducing a daemon-functionality, I am not sure about it, because it would make the application not so simple any more).

I think it is possible, to write a udev rule, which executes a commend, when something is plugged in. E.g. (not tested)

# logitech G733
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="0ab5", TAG+="uaccess" RUN+="/usr/local/bin/headsetcontrol -l 0"
seifrox commented 3 years ago

Hi, Thanks for your answer, I tried it did not work. Then I did some research into udev rules and fixed your suggestion up, it was missing the ACTION (all the commands for documentation purposes):

sudo vi /etc/udev/rules.d/70-headsets.rules

add the following lines:

# logitech G733
KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="0ab5", TAG+="uaccess"  ACTION=="add" RUN+="/usr/local/bin/headsetcontrol -l 0"

reload udev rules

sudo udevadm control --reload-rules && udevadm trigger

The outcome is unfortunately that it only works if the USB receiver is plugged in while the headset has power. So it is basically the same issue, why just setting headsetcontrol -l 0 on startup does not work. The USB Receiver is plugged in from the start and never removed. Every time I turn off/on the power on the headset, I need to recall headsetcontrol -l 0 (at least for now I added a clickable icon to my status bar, so it is more comfortable, but having it done automatically would be way better.

I also investigated further, how to detect that the headset is turned on and found acpi_listen (see script to react to unplug). In theory it could be useful to react on the power button. However, while I receive events for the volume up/down button on the headset, there is nothing on the mute and power buttons :/

I think even if you would write your application in a more complex way to act as a daemon, it would not solve this issue.

Any more ideas, that I could test / play around with?

BR, Alex

Sapd commented 3 years ago

However, while I receive events for the volume up/down button on the headset, there is nothing on the mute and power buttons

I think there is, however only in software mode. In software mode, one also receives packets, wether the headset is connected/disconnected etc. See here: https://github.com/Sapd/HeadsetControl/issues/104#issuecomment-695334072 (only tested on Corsair, but I think this is the same with logitech).

However the software mode has the disadvantage, that a daemon functionality is required, as the mute button won't work by itself any more.

core1024 commented 3 years ago

I personally found out that I can use the battery level as a test whether the headset is on or off. So I wrote this script:

#!/usr/bin/env bash

# You can view all audio sinks by `pactl list short sinks`
# The current sink can be obtained with this command `pactl info | grep "Default Sink"`

SPEAKERS_SINK=1
HEADSET_SINK=2

set_default_sink() {
  pactl set-default-sink $1
  for i in $(pactl list short sink-inputs | cut -f 1); do
    pactl move-sink-input $i $1;
  done
}

while true; do
  LAST_BATTERY_LEVEL="$BATTERY_LEVEL"
  BATTERY_LEVEL=$(headsetcontrol -cb 2>/dev/null)

  if [ -z "$LAST_BATTERY_LEVEL" ] && [ -n "$BATTERY_LEVEL" ]; then
    # Headset connected
    headsetcontrol -cl0
    set_default_sink $HEADSET_SINK
  elif [ -n "$LAST_BATTERY_LEVEL" ] && [ -z "$BATTERY_LEVEL" ]; then
    # Headset disconnected
    set_default_sink $SPEAKERS_SINK
  fi
  sleep 2
done

When the headset is detected it turns off the lights and switches the output. It is not perfect as the state must be pulled. Anyway. It works for me. Could be useful to someone else too.

thiago-buarqque commented 10 months ago

Thanks for your program @Sapd and the script @core1024. Have a good one

qoijjj commented 8 months ago

I'm working on a tiny rust applet that provides a GUI and a daemon to persistently manage headsetcontrol state in an easily adjustable and configurable way.

https://github.com/qoijjj/HeadsetController

It's very rudimentary for now, but a prerelease appimage is available. It still needs work especially to enable it to start on boot, support all the other headsetcontrol parameters, and provide a flatpak/rpm/deb. Testing/issues/contributions/etc are all appreciated.

Hopefully once it's released it can provide a common solution for all of us who are sick of constantly running headsetcontrol -l 0 :smile: