Coder Social home page Coder Social logo

deckmaster's Introduction

deckmaster

Latest Release Go Doc Software License Build Status Go ReportCard

An application to control your Elgato Stream Deck on Linux

Features

  • Multiple pages & navigation between decks
  • Buttons (icons & text)
  • Background images
  • Brightness control
  • Supports different actions for short & long presses
  • Comes with a collection of widgets:
    • Buttons
    • Time (with formatting)
    • CPU/Mem usage
    • Weather
    • Command output
    • Recently used windows (X11-only)
  • Lets you trigger several actions:
    • Run commands
    • Emulate a key-press
    • Paste to clipboard
    • Trigger a dbus call

Installation

Packages

From source

Make sure you have a working Go environment (Go 1.17 or higher is required). See the install instructions.

To install deckmaster, simply run:

git clone https://github.com/muesli/deckmaster.git
cd deckmaster
go build

System Setup

On Linux you need to set up some udev rules to be able to access the device as a regular user. Edit /etc/udev/rules.d/99-streamdeck.rules and add these lines:

SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="0060", MODE:="666", GROUP="plugdev", SYMLINK+="streamdeck"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="006d", MODE:="666", GROUP="plugdev", SYMLINK+="streamdeck"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="0080", MODE:="666", GROUP="plugdev", SYMLINK+="streamdeck"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="0063", MODE:="666", GROUP="plugdev", SYMLINK+="streamdeck-mini"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="006c", MODE:="666", GROUP="plugdev", SYMLINK+="streamdeck-xl"

Make sure your user is part of the plugdev group and reload the rules with sudo udevadm control --reload-rules. Unplug and re-plug the device, and you should be good to go.

Starting deckmaster automatically

If you want deckmaster to be started automatically upon device plugin, you can use systemd path activation, adding streamdeck.path and streamdeck.service files to $HOME/.config/systemd/user.

streamdeck.path contents:

[Unit]
Description="Stream Deck Device Path"

[Path]
# the device name will be different if you use streamdeck-mini or streamdeck-xl
PathExists=/dev/streamdeck
Unit=streamdeck.service

[Install]
WantedBy=multi-user.target

streamdeck.service contents:

[Unit]
Description=Deckmaster Service

[Service]
# adjust the path to deckmaster and .deck file to suit your needs
ExecStart=/usr/local/bin/deckmaster --deck path-to/some.deck
Restart=on-failure
ExecReload=kill -HUP $MAINPID

[Install]
WantedBy=default.target

Then enable and start the streamdeck.path unit:

systemctl --user enable streamdeck.path
systemctl --user start streamdeck.path

Usage

Start deckmaster with the initial deck configuration you want to load:

deckmaster -deck deck/main.deck

You can control the brightness, in percent:

deckmaster -brightness 50

Control a specific streamdeck:

deckmaster -device [serial number]

Set a sleep timeout after which the screen gets turned off:

deckmaster -sleep 10m

Configuration

You can find a few example configurations in the decks directory. Edit them to your needs!

Widgets

Any widget is build up the following way:

[[keys]]
  index = 0

index needs to be present in every widget and describes the position of the widget on the streamdeck. index is 0-indexed and counted from top to bottom and left to right.

Update interval for widgets

Optionally, you can configure an update interval for each widget:

[keys.widget]
  id = "button"
  interval = 500 # optional

The attribute interval defines the time in ms between two consecutive updates of a widget.

Button

A simple button that can display an image and/or a label.

[keys.widget]
  id = "button"
  [keys.widget.config]
    icon = "/some/image.png" # optional
    label = "My Button" # optional
    fontsize = 10.0 # optional
    color = "#fefefe" # optional
    flatten = true # optional

If flatten is true all opaque pixels of the icon will have the color color.

Recent Window (requires X11)

Displays the icon of a recently used window/application. Pressing the button activates the window.

[keys.widget]
  id = "recentWindow"
  [keys.widget.config]
    window = 1
    showTitle = true # optional

If showTitle is true, the title of the window will be displayed below the window icon.

Time

A flexible widget that can display the current time or date.

[keys.widget]
  id = "time"
  [keys.widget.config]
    format = "%H;%i;%s"
    font = "bold;regular;thin" # optional
    color = "#fefefe" # optional
    layout = "0x0+72x24;0x24+72x24;0x48+72x24" # optional

With layout custom layouts can be definded in the format [posX]x[posY]+[width]x[height].

Values for format are:

% gets replaced with
%Y A full numeric representation of a year, 4 digits
%y A two digit representation of a year
%F A full textual representation of a month, such as January or March
%M A short textual representation of a month, three letters
%m Numeric representation of a month, with leading zeros
%l A full textual representation of the day of the week
%D A textual representation of a day, three letters
%d Day of the month, 2 digits with leading zeros
%h 12-hour format of an hour with leading zeros
%H 24-hour format of an hour with leading zeros
%i Minutes with leading zeros
%s Seconds with leading zeros
%a Lowercase Ante meridiem and Post meridiem
%t Timezone abbreviation

Top

This widget shows the current CPU or memory utilization as a bar graph.

[keys.widget]
  id = "top"
  [keys.widget.config]
    mode = "cpu"
    color = "#fefefe" # optional
    fillColor = "#d497de" # optional

There are two values for mode: cpu and memory.

Command

A widget that displays the output of commands.

[keys.widget]
  id = "command"
  [keys.widget.config]
    command = "echo 'Files:'; ls -a ~ | wc -l"
    font = "regular;bold" # optional
    color = "#fefefe" # optional
    layout = "0x0+72x20;0x20+72x52" # optional

Weather

A widget that displays the weather condition and temperature.

[keys.widget]
  id = "weather"
  [keys.widget.config]
    location = "MyCity" # optional
    unit = "celsius" # optional
    color = "#fefefe" # optional
    flatten = true # optional
    theme = "openmoji" # optional

The supported location types can be found here. The unit has to be either celsius or fahrenheit. If flatten is true all opaque pixels of the condition icon will have the color color. In case theme is set corresponding icons with correct names need to be placed in ~/.local/share/deckmaster/themes/[theme]. The default icons with their respective names can be found here.

Actions

You can hook up any key with several actions. A regular keypress will trigger the widget's configured keys.action, while holding the key will trigger keys.action_hold.

Switch deck

[keys.action]
  deck = "relative/path/to/another.deck"

Run a command

[keys.action]
  exec = "some_command --with-parameters"

Emulate key-presses

[keys.action]
  keycode = "Leftctrl-C"

Emulate a series of key-presses with delay in between:

[keys.action]
  keycode = "Leftctrl-X+500 / Leftctrl-V / Num1"

A list of available keycodes can be found here: keycodes

Paste to clipboard

[keys.action]
  paste = "some text"

Trigger a dbus call

[keys.action]
  [dbus]
    object = "object"
    path = "path"
    method = "method"
    value = "value"

Device actions

Increase the brightness. If no value is specified, it will be increased by 10%:

[keys.action]
  device = "brightness+5"

Decrease the brightness. If no value is specified, it will be decreased by 10%:

[keys.action]
  device = "brightness-5"

Set the brightness to a specific value between 0 and 100:

[keys.action]
  device = "brightness=50"

Put the device into sleep mode, blanking the screen until the next key gets pressed:

[keys.action]
  device = "sleep"

Background Image

You can configure each deck to display an individual wallpaper behind its widgets:

background = "/some/image.png"

Re-using another deck's configuration

If you specify a parent inside a deck's configuration, it will inherit all of the parent's settings that are not overwritten by the deck's own settings. This even works recursively:

parent = "another.deck"

More Decks!

Made your own useful decks? Submit a pull request!

Feedback

Got some feedback or suggestions? Please open an issue or drop me a note!

deckmaster's People

Contributors

boj avatar comradin avatar dependabot[bot] avatar endocrimes avatar henryso avatar hoodeddeath avatar marcusramberg avatar muesli avatar nikolay avatar pheerai avatar rubiojr avatar tenfourty avatar tvidal-net avatar xdevla avatar zmoooooritz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

deckmaster's Issues

device = "sleep" on action_hold doesn't work properly

When placing the device = "sleep" action on the action_hold of a key, it doesn't work as it should. The device will "wake up" as soon as the key is released. I tried modifying github.com/muesli/streamdeck to ignore "wake-up" events that all button release, but this doesn't quite fix the problem. Deckmaster still thinks the button is still held down because it was never aware that the device went to sleep.

There are three solutions that come to my mind.

  1. Allow a channel to be passed to streamdeck.Device to receive events such as this so that (in this case) Deckmaster can clear its keystate tracking. Incidentally, adding such a channel may help with the "clear the deck" and "show it again" sleep-related feature that I'm looking for.
  2. Send key release events for all pressed keys when the device sleeps. This way, it will appear to Deckmaster that all keys are released when the device sleeps and will track that "normally".
  3. Take the key-hold event generation into the streamdeck library somehow. This way, Deckmaster will receive key press and key long-hold events separately and doesn't need to track key timings. However, this makes the streamdeck library more high-level (so perhaps it should be optional somehow).

Which do you prefer, or do you prefer something else?

Documentation for interval value listing it under keys section is incorrect

The documentation in this repo lists interval as being set alongside the index value, within the keys section. After looking through the code and some testing, I have found out the hard way that the interval value needs to be set within the keys.widget section, alongside the id value.

Example originally based on documentation:

[[keys]]
  index = 0
  interval = 1000
  [keys.widget]
    id = "top"
    [keys.widget.config]
      mode = "cpu"

Correct example:

[[keys]]
  index = 0
  [keys.widget]
    id = "top"
    interval = 1000
    [keys.widget.config]
      mode = "cpu"

XGB: conn.go:47: Could not get authority info: EOF

The XGB include breaks if you aren't running XWindows (i.e. running Wayland). There is a uinput go library that works for both Wayland and X11. I think the desktop code also uses the XGB for 'last window' widget, etc, so it may not be a direct swap, but it would be nice if we didn't throw errors if you aren't running XWindows. Maybe at least a toggle to not run that code-path as a config?

Error loading template example deck

Hi this is quite a great project with a fully install file that will be perfect to used that ctrl unit. But i cannot get it to work or the example file is not readed or so.. over a Debian VERSION_CODENAME="bookworm"
Here all the details:

deckmaster -verbose -deck ~/main.deck
Found device with serial Axxxxxxx (15 buttons, firmware 1.0.170133)
Could not create virtual input device (/dev/uinput): failed to create virtual keyboard device: could not open device file
Emulating keyboard events will be disabled!
Loading deck: /home/xpuser/main.deck
wait for event: BadDrawable {NiceName: Drawable, Sequence: 2, BadValue: 0, MinorOpcode: 2, MajorOpcode: 145}
Can't load deck: toml: line 1: expected '.' or '=', but got '{' instead

  • Stream deck : lsusb -v
    model 15 bts= idVendor 0x0fd9 / idProduct 0x0060 / bcdDevice 1.0

sudo apt install ./deckmaster_0.9.0_linux_amd64.deb

cat /etc/udev/rules.d/99-streamdeck.rules
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="0060", TAG+="uaccess"

or change by :
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="0060", MODE:="666", GROUP="plugdev", SYMLINK+="streamdeck"

and reload by :
sudo udevadm control --reload-rules / sudo udevadm trigger or a reboot.

Over group, the user is the full admin of the system and also member of the group plugdev. Same thing if i do :
usermod -aG plugdev usrxyz

When i check the device i do have this:
ls -l /dev/bus/usb/003/004
crw-rw-r--+ 1 root root 189, 259 Oct 20 19:28 /dev/bus/usb/003/004

I also download your example file and put direct : in /home/userxyz/main.deck
via:
wget https://github.com/muesli/deckmaster/raw/master/decks/main.deck

Thanks for tips or so..

"no Stream Deck devices found" When there is definetly a stream deck connected.

Edit: I was just being dumb and forgot to save the changes to xx-streamdeck.rules, you can close this

T:  Bus=01 Lev=01 Prnt=01 Port=01 Cnt=01 Dev#= 14 Spd=480 MxCh= 0
D:  Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs=  1
P:  Vendor=0fd9 ProdID=0063 Rev=02.00
**S:  Manufacturer=Elgato Systems
S:  Product=Stream Deck Mini**
S:  SerialNumber=BL44K1B03462
C:  #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=200mA
I:  If#= 0 Alt= 0 #EPs= 2 Cls=03(HID  ) Sub=00 Prot=00 Driver=usbhid
E:  Ad=02(O) Atr=03(Int.) MxPS=1024 Ivl=125us
E:  Ad=81(I) Atr=03(Int.) MxPS= 512 Ivl=125us

This is a snippet from the output of usb-devices.
That's a stream deck mini, seamingly connecting just fine to my system. Boatswain works fine.

Deckmaster throws Unable to initialize Stream Deck: no Stream Deck devices found

And I don't know neither enough linux nor enough Go to figure out why. However, this does seem like a bug.

Any way to define hold actions for buttons?

Looking in eventLoop function of main.go, there's a check for if a given key is still pressed for a long press action, and widget_recent_window.go seems to (as far as I can tell) utilize that in order to close a window on long press. So is it currently possible to define a hold action (such as hold a defined key while holding key on the deck) or would it be possible to add such a feature?

Is Deckmaster wayland ready or fails?

I'm running swayvm and wayland
Does deckmaster work under wayland?

If yes, I'll continue trying to get things to work with sway on nixOS

If no, suggestions on a Streamdeck program that works with wayland, with more functionality than the very limited boatswain

Thanks for replies

[Feature Idea] How feasible would it be to add the functionality to reload a button without reloading the whole config?

What I'm thinking would be a good addition would be an action option to reload the display of a button. For example, you have a button which outputs the result of some command/script, you could set action_hold to reload and it would re-run that script/command for an updated result.

I'm not familiar with Go, so I'm not even at a point of understanding how this program works as is, but I am planning to try to understand it because this reloadable button idea would be a major improvement in my opinion.

deckmaster 0.8.0 requires libc 2.34

Using deckmaster_0.8.0_linux_amd64.deb

jens@shaun-works:~$ deckmaster -version
deckmaster: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by deckmaster)

However the latest one available on a regular Pop!OS (and maybe Ubuntu) stable is 2.33

jens@shaun-works:~$ sudo apt show libc6
Package: libc6
Version: 2.33-0ubuntu5

Building from source works fine.

Using colon in time format yield to miniscule font

If I use a colon as time separator, it yield to a minuscule font (see photo).

[[keys]]
  index = 0
  [keys.widget]
    id = "button"
    [keys.widget.config]
      label = "Music"
  [keys.action]
    deck = "music.deck"

[[keys]]
  index = 3
  [keys.widget]
    id = "time"
    [keys.widget.config]
      format = "%H:%i;%s"

image

Dim brightness when screens are turned off in powersave mode

Currently the button brightness stays at whatever level it's set at even when the screens are turned off in power save mode. It would be great if the brightness was turned to the minimum when the screens are turned off (similar to what happens when the computer is put into sleep mode).

I'd be happy to try to implement this functionality if you could give me a few pointers on how you think it could be done.

stream deck display stays black

Hey, thanks for the really promising looking project.

Trying to run deckmaster with my stream deck mini nothing is displayed on the buttons of the deck with the latest master branch on my Arch Linux machine.
I don't see any errors in the output of deckmaster and button presses are registered perfectly fine:

➜ ./deckmaster -verbose -deck ~/.config/deckmaster/main.deck
Found device with serial BL36K1B46596 (6 buttons, firmware 3.00.001)
wait for event: BadDrawable {NiceName: Drawable, Sequence: 2, BadValue: 0, MinorOpcode: 2, MajorOpcode: 144}
Loading deck: /home/lnqs/.config/deckmaster/main.deck
Triggering long action for key 1
Triggering short action for key 2

Anyway, the display stays just black.

I set up the udev rules:

➜ cat /etc/udev/rules.d/99-streamdeck.rules
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="0060", MODE:="666", GROUP="plugdev", SYMLINK+="streamdeck"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="006d", MODE:="666", GROUP="plugdev", SYMLINK+="streamdeck"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="0080", MODE:="666", GROUP="plugdev", SYMLINK+="streamdeck"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="0063", MODE:="666", GROUP="plugdev", SYMLINK+="streamdeck-mini"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="006c", MODE:="666", GROUP="plugdev", SYMLINK+="streamdeck-xl"

Access rights should also be fine:

➜ ls -l /dev/streamdeck-mini 
lrwxrwxrwx 1 root root 15 Feb 12 00:34 /dev/streamdeck-mini -> bus/usb/001/002

➜ ls -l /dev/bus/usb/001/002
crw-rw-rw- 1 root plugdev 189, 1 Feb 12 01:27 /dev/bus/usb/001/002

➜ groups      
vboxusers input wheel lnqs plugdev

My deck config (tried several ones but stuck to this as a minimal example in the end):

➜ cat ~/.config/deckmaster/main.deck
[[keys]]
  index = 0
  [keys.widget]
    id = "button"
    [keys.widget.config]
      label = "My Button"

Any ideas what might be wrong or how to debug it?

Multi Line Command Output

Not Sure if this is already possible with the layout property.
But would it somehow be possible to dynamically set the newline when using the keys.widget.config.command functionality?

For example:

-> playerctl metadata title | tr ' ' '\n'
Soldier
of
Heaven

Currently, the newline gets ignored. And it gets rendered as "Soldier of Heaven" instead of
"Solider
of
Heaven"

Deckmaster process randomly using large amount of processor power

Description
At seemingly random times, the deckmaster process begins consuming roughly 20% of my Ryzen 7 3700X. I am currently unable to confirm if this is always the case, but for the most recent occurence, the log through systemd contians these two lines at the end:

XGB: xgb.go:455: A read error is unrecoverable: read unix @->/tmp/.X11-unix/X0: read: connection reset by peer
XGB: xgb.go:455: A read error is unrecoverable: EOF

Although this error seems to be the result of logging out and logging back in, this is the only clue I have. If needed for further info, I can run deckmaster through a normal shell instance to get more complete output. If there are verbosity options available, please inform.

Desktop:

  • Distro: Arch
  • Deckmaster Version: 0.5.1

Log
Full output of systemctl --user status streamdeck.service:

● streamdeck.service - Deckmaster Service
     Loaded: loaded (/home/death/.config/systemd/user/streamdeck.service; disabled; vendor preset: enabled)
     Active: active (running) since Thu 2021-11-11 23:43:14 MST; 1h 44min ago
TriggeredBy: ● streamdeck.path
   Main PID: 5242 (deckmaster)
      Tasks: 24 (limit: 38376)
     Memory: 828.9M
        CPU: 4h 33min 18.437s
     CGroup: /user.slice/user-1000.slice/[email protected]/app.slice/streamdeck.service
             └─5242 /usr/bin/deckmaster -deck /home/death/.local/share/streamdeck-deckmaster/main.deck -brightness 60

Nov 11 23:43:20 Scarlet deckmaster[5242]: Active window changed to Opera (60817417, Nmap - ArchWiki - Opera)
Nov 11 23:43:20 Scarlet deckmaster[5242]: Active window changed to Opera (60817419, 41124 – (need-to-run-perl-cleaner) configure: error: XML::Parser perl module is required for [...] - YOU NEED TO RUN `perl-cleaner' - Opera)
Nov 11 23:43:20 Scarlet deckmaster[5242]: Active window changed to Opera (60817420, Gentoo Forums :: View topic - media-libs/libsdl2 fails to build, requires wayland? (gles2) - Opera)
Nov 11 23:43:21 Scarlet deckmaster[5242]: Active window changed to Opera (60817421, /etc/portage/package.mask - Gentoo Wiki - Opera)
Nov 11 23:43:21 Scarlet deckmaster[5242]: Active window changed to Opera (60817422, AUR (en) - minecraft-server-manager - Opera)
Nov 11 23:43:21 Scarlet deckmaster[5242]: Active window changed to Opera (60817423, Welcome to Opera - Opera)
Nov 11 23:43:21 Scarlet deckmaster[5242]: Active window changed to Opera (60817425, Opera - Update complete! - Opera)
Nov 11 23:43:21 Scarlet deckmaster[5242]: Active window changed to Opera (60817426, [1.17.1 (Crash/No Boot)] On launch a Minecraft window never appears and comes with a crash (Mac 2012 Macos Mojave) · Issue #6278 · sp614x/optifine - Opera)
Nov 11 23:43:21 Scarlet deckmaster[5242]: XGB: xgb.go:455: A read error is unrecoverable: read unix @->/tmp/.X11-unix/X0: read: connection reset by peer
Nov 11 23:43:21 Scarlet deckmaster[5242]: XGB: xgb.go:455: A read error is unrecoverable: EOF

Configuration:

[[keys]]
  index = 0
  [keys.widget]
    id = "time"
    interval = 1000
    [keys.widget.config]
      format = "%D;%M;%d"
  [keys.action]
    exec = "systemctl --user restart streamdeck.service"

[[keys]]
  index = 1
  [keys.widget]
    interval = 1000
    id = "time"
    [keys.widget.config]
      format = "%h:%i;%s %a"

[[keys]]
  index = 2
  [keys.widget]
    id = "weather"
    interval = 60000
    [keys.widget.config]
      location = "orem"
      unit = "fahrenheit"

[[keys]]
  index = 3
  [keys.widget]
    id = "top"
    [keys.widget.config]
      mode = "cpu"

[[keys]]
  index = 4
  [keys.widget]
    id = "top"
    [keys.widget.config]
      mode = "memory"

[[keys]]
  index = 5
  [keys.widget]
    id = "button"
    [keys.widget.config]
      label = "Vol \\/"
  [keys.action]
    keycode = "Volumedown"

[[keys]]
  index = 6
  [keys.widget]
    id = "button"
    [keys.widget.config]
      label = "Vol /\\"
  [keys.action]
    keycode = "Volumeup"

[[keys]]
  index = 7
  [keys.widget]
    id = "button"
    [keys.widget.config]
      label = "Mute"
  [keys.action]
    keycode = "mute"

[[keys]]
  index = 8
  [keys.widget]
    id = "command"
    interval = 60000
    [keys.widget.config]
      command = "echo 'Avail'; echo 'Root:'; df --output=avail --human-readable /dev/mapper/main-root | tail -n 1 | sed 's/^ *//g'"

[[keys]]
  index = 9
  [keys.widget]
    id = "command"
    interval = 60000
    [keys.widget.config]
      command = "echo 'Avail'; echo 'Extra:'; df --output=avail --human-readable /dev/mapper/cryptext | tail -n 1 | sed 's/^ *//g'"

[[keys]]
  index = 10
  [keys.widget]
    id = "command"
    interval = 60000
    [keys.widget.config]
      command = "echo 'Avail'; echo 'Swap:'; /home/death/scripts/output-free-swap"

[[keys]]
  index = 11
  [keys.widget]
    id = "button"
    [keys.widget.config]
      label = "Play/Pause"
  [keys.action]
    keycode = "Playpause"

[[keys]]
  index = 12
  [keys.widget]
    id = "button"
    [keys.widget.config]
      label = "Deafen"
  [keys.action]
    keycode = "Rightshift-F7"

[[keys]]
  index = 13
  [keys.widget]
    id = "button"
    [keys.widget.config]
      label = "Mute"
  [keys.action]
    keycode = "Rightshift-F8"

[[keys]]
  index = 14
  [keys.widget]
    id = "button"
    [keys.widget.config]
      label = "Screen"
  [keys.action]
    exec = "/home/death/scripts/rotate-screen"
  [keys.action_hold]
    exec = "/home/death/scripts/rotate-screen --fix"

[[keys]]
  index = 15
  [keys.widget]
    id = "button"
    [keys.widget.config]
      icon = "/opt/discord/discord.png"
  [keys.action]
    exec = "discord"

[[keys]]
  index = 16
  [keys.widget]
    id = "command"
    interval = 3600000
    [keys.widget.config]
      command = "echo 'Find'; echo 'Cursor'"
  [keys.action]
    exec = "xfce4-find-cursor"

[[keys]]
  index = 21
  [keys.widget]
    id = "command"
    [keys.widget.config]
      command = "echo 'CPU Top:'; /home/death/scripts/get-top-cpu-usage"

[[keys]]
  index = 22
  [keys.widget]
    id = "button"
    [keys.widget.config]
      icon = "/home/death/pictures/mango.png"
  [keys.action]
    exec = "xdotool key F14"

[[keys]]
  index = 23
  [keys.widget]
    id = "button"
    [keys.widget.config]
      icon = "/usr/share/icons/hicolor/256x256/apps/steam.png"
  [keys.action]
    exec = "steam-runtime"

[[keys]]
  index = 24
  [keys.widget]
    id = "command"
    [keys.widget.config]
      command = "echo \"CPU\"; /home/death/scripts/output-tctl"

[[keys]]
  index = 25
  [keys.widget]
    id = "command"
    [keys.widget.config]
      command = "echo \"GPU\"; /home/death/scripts/output-edge"

[[keys]]
  index = 26
  [keys.widget]
    id = "command"
    interval = 10000
    [keys.widget.config]
      command = "echo \"BATT\"; /home/death/scripts/print-battery-percent"

[[keys]]
  index = 29
  [keys.widget]
    id = "command"
    [keys.widget.config]
      command = "echo 'Hold'; echo 'LMB'"
  [keys.action]
    exec = "xdotool mousedown 1"
  [keys.action_hold]
    exec = "xdotool keydown e"

[[keys]]
  index = 30
  [keys.widget]
    id = "button"
    [keys.widget.config]
      icon = "/usr/share/icons/hicolor/256x256/apps/opera.png"
  [keys.action]
    exec = "opera"

[[keys]]
  index = 31
  [keys.widget]
    id = "command"
    [keys.widget.config]
      command = "echo 'Togg'; echo 'F9'"
  [keys.action]
    exec = "/home/death/toggle-f9"

label line breaks

Hi and thanks for this project.
I do a fair amount of tech support and it would be helpful to be able to add line breaks in the label property of a key.

I've tried '\n' and the ANSI code already but they didn't work.

Being able to add line breaks allows me to better describe the pasted text (whereas currently, all the text gets smaller to fit on the one line)

Thanks again

Trying to start deckmaster with no active window panics

I don't know much about xorg, but it doesn't happen once you touch the background with the mouse (making the background the first "active window" I guess?), i.e. right after a fresh start in my raspi with the default desktop:

panic: runtime error: index out of range [0] with length 0                                                                                                                                                           
                                                                                                                                                                                                                     
goroutine 1 [running]:                                                                                                                                                                                               
github.com/BurntSushi/xgb.Get32(...)                                                                                                                                                                                 
        /home/rubiojr/go/pkg/mod/github.com/!burnt!sushi/[email protected]/help.go:87                                                                                                           
main.Xorg.active(0x2062af0, 0x20803c0, 0x389, 0x21b1540, 0x21b1550, 0x21b1570, 0x21b1590, 0x0, 0x0, 0x0, ...)                                                                                                        
        /home/rubiojr/git/muesli/deckmaster/desktop_unix.go:173 +0x108                                                                                                                                               
main.Xorg.window(0x2062af0, 0x20803c0, 0x389, 0x21b1540, 0x21b1550, 0x21b1570, 0x21b1590, 0x0, 0x0, 0x0, ...)                                                                                                        
        /home/rubiojr/git/muesli/deckmaster/desktop_unix.go:219 +0x30                                                                                                                                                
main.(*Xorg).TrackWindows(0x40f708, 0x219ccc0, 0x3b9aca00, 0x0)                                                                                                                                                      
        /home/rubiojr/git/muesli/deckmaster/desktop_unix.go:92 +0x34                                                                                                                                                 
main.main()                                                                                                                                                                                                          
        /home/rubiojr/git/muesli/deckmaster/main.go:85 +0x1cc                                                                                                                                                        

This is the workaround I'm using, no idea how to correctly solve it unfortunately:

diff --git a/desktop_unix.go b/desktop_unix.go
index b30a702..b8987f1 100644
--- a/desktop_unix.go
+++ b/desktop_unix.go
@@ -170,6 +170,9 @@ func (x Xorg) active() xproto.Window {
        if err != nil {
                return x.root
        }
+       if len(p.Value) == 0 {
+               return 0
+       }
        return xproto.Window(xgb.Get32(p.Value))
 }

How should disconnect / reconnect be handled?

When I power off the hub that my deckmaster is connected to, deckmaster will crash. Not every crash results in the same error though.

When keeping the hub off for a long time, I got this SERV:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x60 pc=0x57d967]

goroutine 1 [running]:
github.com/karalabe/hid.(*Device).SendFeatureReport(0x0, {0xc0005082a0, 0x20, 0x20})
        /home/erwin/go/pkg/mod/github.com/karalabe/[email protected]/hid_enabled.go:211 +0x47
github.com/muesli/streamdeck.Device.sendFeatureReport(...)
        /home/erwin/go/pkg/mod/github.com/muesli/[email protected]/streamdeck.go:475
github.com/muesli/streamdeck.Device.Reset({{0xc00002a240, 0xc}, {0xc00002a2e0, 0xc}, 0x5, 0x3, 0xf, 0x48, 0x7c, 0x10, ...})
        /home/erwin/go/pkg/mod/github.com/muesli/[email protected]/streamdeck.go:233 +0x92
main.closeDevice(0xc0000b0b60)
        /home/erwin/SourceInstall/deckmaster/main.go:172 +0x98
main.run()
        /home/erwin/SourceInstall/deckmaster/main.go:285 +0x642
main.main()
        /home/erwin/SourceInstall/deckmaster/main.go:308 +0x1a5

Yet when turning off more quickly I got:

Unable to reset Stream Deck
error: cannot write image page 0 of 4 (3660 image bytes) 1024 bytes: hidapi: unknown failure

Of course I can work can work around by not disconnecting :-)

change output / color depending on condition

Hi,

I just recently discovered this project and really like it! I am mainly using it for controlling and monitoring, and it'd be great if the following was possible:

[[keys]]
  index = 15
[keys.widget]
  id = "command"
  [keys.widget.config]
    command = "cat /tmp/true_false'"
    font = "regular;bold;italic" # optional
    # if content of `cat /tmp/true_false` is true
    color = "#E06" # optional
    # else if content of `cat /tmp/true_false` is false
    color = "#fefefefe`
    # else
    color = #f0f0f0`
    # layout = "0x0+72x20;0x20+72x52" # optional

So basically, change a button depending on a state condition. One could even take this one step further with output... if it was true, don't display "true", but rather "switch: on" (in color x), and if it was false, display "switch: off" (in color y).

Can this be achieved with the current version of the program and/or will it be possible in later releases?

Thank you in advance for your help :)

deckmaster breaks when failing to load missing font

First time running after successfully building I got hit with an error: cannot find font 'Roboto-Regular.ttf' in user or system directories. This is easily fixable by downloading the Roboto font family (eg from Google) and installing it to /usr/share/icons or whatever; however, it doesn't seem like something that should break execution if the font can't be found.

Proposed Solution:

  • Probably some sort of try/catch block around the font loading, with a default fallback.

A way to debug `exec`?

I'm trying to trigger a webhook with httpie (curl alternative) like this:

[[keys]]
  index = 13
  [keys.widget]
    id = "button"
    [keys.widget.config]
      icon = "./assets/Nightlife/misc/Screenshot.png"
  [keys.action]
    exec = "https POST home-assistant.service.consul/api/webhook/media"

It works when I run it myself and doesn't when it is triggered by deckmaster.

I'm not sure how to debug it since there is no log. I've tried to execute a script inside of which I've redirected command stdout and stdin to a file, but the file is not created. However if I add exit 1 to the end of the script I will get command failed: exit status 1 meaning it did run the script.

I guess this is something to do with how golang exec module works?

DBus calls do not work if the current readme example is followed

Spent too long trying to figure this out, but the readme example of a DBus call does not import values at all.

The non-functional example in the readme is

[keys.action]
  [dbus]
    object = "object"
    path = "path"
    method = "method"
    value = "value"

In order to make it work, dbus must be added to the keys.action

[keys.action.dbus]
    object = "object"
    path = "path"
    method = "method"
    value = "value"

I've confirmed this works, at least for session bus calls, on 0.9.0. Will submit a change to readme to clear up confusion

Building from source requires Go version >1.13

README.md states "Go 1.12 or higher is required", but I just tried to build this on 1.13.4 and got build github.com/muesli/deckmaster: cannot load embed: malformed module path "embed": missing dot in first path element error. Upgrading to Go version 1.17.2 resolved this issue.

Proposed solution:

  • Just update README.md to reflect higher version number needed.

More automated AUR package

Hi @muesli,

Let me start by saying a massive thank you for building, and sharing this awesome project! I have a cool Stream Deck setup on me Linux machine thanks to you.

I noticed you (or someone using your name) created an AUR package of deckmaster, that helped me get started, but left a few steps remaining. I decided to automate some of these steps locally, and wanted to share that with you.

I've posted a comment over on the AUR website, with a patch, and I've pushed my work up to GitHub in case you'd prefer that.

What I've added:

  • udev rules that will be installed automatically (I replaced the idProduct with the ID of my Stream Deck because I wanted that name - maybe there should be four lines in this file with a name I'm not aware of?)
  • [email protected] unit that will watch the symlink path you specify (e.g. systemctl --user enable [email protected])
  • [email protected] that will start deckmaster inside ~/.config/deckmaster/, and look for a deck that shares a name with your symlink path from above.

I think I've duplicated some effort as the missing ttf-roboto dependency has been mentioned in the non-git version of the package. Sorry about that!

I'm running this locally now, and it's working spectacularly! Thanks again for sharing your awesome work. 🙇

[feature] Animated gifs?

Seems gifs aren't animated when loaded in - I wouldn't expect this to get actioned but it would be the cream on top for deckmaster if they played expected animations.

Background-Image (Wallpaper)

I got a streamdeck recently and came across your implementation to control the streamdeck.
As I used it, I felt like the "Background-Image"-Feature (from the official software) is missing, this means that most of the time one has to create and apply these background images by hand per widget in an image editor.

Therefore I implemented this feature myself background.
Besides the new functionality, it cleans up the different widgets which makes the creation of new ones easier.
One downside of this patch though, is the slightly increased memory footprint as well as some computational overhead for the blending of fore- and background.

As seen in the patch this would also require a small change in streamdeck where we would need a new value for each device which describes the distance / padding between the buttons.

Some X Window Icons don't work

Running on Fedora 33 (and 34 beta) the recent window widget is not able to detect the icon of the window which means some recent windows aren't shown.

You can reproduce this with the Spotify app by switching to it and then away.

There is an error message on the console:
Could not find icon for window 113246215.

From a quick look at the code it seems that if there is an error getting the icon you ignore the window, but perhaps you could try to get the window title and insert some text instead?

"no Stream Deck devices found" for new (?) StreamDeck Mini

I have a new StreamDeck mini with USB ID 0fd9:0090

Bus 001 Device 007: ID 0fd9:0090 Elgato Systems GmbH Stream Deck Mini

I've added this to udev rules and reloaded.

I've tried the various packages on Arch and built myself. Also quickly tried on Fedora and running as root, I always get the "no Stream Deck devices found" error.

Could there be some incompatibility with this version (I presume it's more recent)?

Looks fine in lsusb, dmesg etc. Also works as expected in Windows and in Arch in the python streamdeck-ui.

reuse buttons across multiple decks

Hi, thank you for this amazing implementation of the stream deck.

I am looking for a way to keep some common buttons (like cpu, memory, weather) present in multiple decks.

Is there any way to keep them in a separate deck file and just include them to whichever other deck I want to reuse them to avoid copy/paste everything? I could not find it in the docs.

Regards.

Cannot get deckmaster to discover my stream deck

deckmaster quits with message no Stream Deck devices found

Running Pop!OS 21.04

jens@shaun-works:~$ cat /etc/os-release
NAME="Pop!_OS"
VERSION="21.04"
ID=pop
ID_LIKE="ubuntu debian"
PRETTY_NAME="Pop!_OS 21.04"
VERSION_ID="21.04"
HOME_URL="https://pop.system76.com"
SUPPORT_URL="https://support.system76.com"
BUG_REPORT_URL="https://github.com/pop-os/pop/issues"
PRIVACY_POLICY_URL="https://system76.com/privacy"
VERSION_CODENAME=hirsute
UBUNTU_CODENAME=hirsute
LOGO=distributor-logo-pop-os

udev rules are set

jens@shaun-works:~$ cat /etc/udev/rules.d/99-streamdeck.rules
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="0060", MODE:="666", GROUP="plugdev", SYMLINK+="streamdeck"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="006d", MODE:="666", GROUP="plugdev", SYMLINK+="streamdeck"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="0080", MODE:="666", GROUP="plugdev", SYMLINK+="streamdeck"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="0063", MODE:="666", GROUP="plugdev", SYMLINK+="streamdeck-mini"
SUBSYSTEM=="usb", ATTRS{idVendor}=="0fd9", ATTRS{idProduct}=="006c", MODE:="666", GROUP="plugdev", SYMLINK+="streamdeck-xl"

user is member of the plugdev group

jens@shaun-works:~$ groups
jens sudo plugdev docker

streamdeck.path

jens@shaun-works:~$ cat ~/.config/systemd/user/streamdeck.path 
[Unit]
Description="Stream Deck Device Path"

[Path]
# the device name will be different if you use streamdeck-mini or streamdeck-xl
PathExists=/dev/streamdeck-xl
Unit=streamdeck.service

[Install]
WantedBy=multi-user.target

streamdeck.service

jens@shaun-works:~$ cat ~/.config/systemd/user/streamdeck.service 
[Unit]
Description=Deckmaster Service

[Service]
# adjust the path to deckmaster and .deck file to suit your needs
ExecStart=/usr/bin/deckmaster --deck /home/jens/streamdeck/streamdeck-xl.deck
Restart=on-failure

[Install]
WantedBy=default.target

deck config file

jens@shaun-works:~$ cat ~/streamdeck/streamdeck-xl.deck
[[keys]]
  index = 0
  [keys.widget]
    id = "top"
    [keys.widget.config]
      mode = "cpu"
      fillColor = "#d497de"

stream deck is connected

jens@shaun-works:~$ ls -al /dev/streamdeck-xl
lrwxrwxrwx 1 root root 15 Jan  4 09:26 /dev/streamdeck-xl -> bus/usb/001/006

Any help is highly appreciated. Thanks!

systemd path trigger in documentation

First, thanks for the hint with the --user switch in systemd, I did not know this one before.

But it does not work with my ArchLinux setup. I suspect that the Modified does not trigger fast enough for the user, as the udev rules will create the /dev/streamdeck link at boot time and when the user login happens the file is already in place and no more changes happen that would allow the path unit to trigger the service.

deckmaster doesnt run

2021-04-29-232520_1726x141_scrot

when i rune deckmaster with any provided sample it doesnt load. i get the following errors.

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.