Open source StreamDeck alternative

josuigoa

Josu Igoa

Posted on February 16, 2023

Open source StreamDeck alternative

I've always been attracted by StreamDeck for developers productivity.

  • Mute/unmute microphone ...*
  • Open all the needed applications when starting the day at once ...*
  • Write log-in information (user/password) ...*

*... with a single click of a button

But, you must buy a hardware of thousands of € or pay a smartphone app (monthly 2.99€) just for testing. Only works for windows & mac and writing plugins is not very straighforward (at least for me).

It is very important for me to create my own plugins

Alternatives

I know there are some alternative solutions that works with smartphones such as touch-portal and macrodeck but they have some things that I don't like.

  • They are closed source (Maybe macrodeck is now open sourced? If it's so, too late, I'm on my way!).
  • You have to install some dependencies (java and .net) to run them.
  • There is no solution for linux machines
  • They have a complex system to create plug-ins (install SDK, create a package...)

So, as any software developer, because the solutions out there weren't satisfing my needs 150%: I created my own solution!

My own solution (a.k.a. Ideckia)

My main goal was to create a tool which was very easy to write plug-ins for it (and hack the existing ones). A tool which was able to work the same way in windows, macos and linux.

The first I though was the name :-) I had the perfect name for it: ideckia

irekia means "open" in my mother language, Basque. And deck... well, you get the reference, right?

After that come the minor things, the plan for the app:

  • Create a server in the computer with duplex communication for the client (smartphone, desktop...).
  • Save all the data in a plain json file. Human readable, no crypto-data
  • Use NodeJS as it is cross-platform
  • Make the actions (or plug-ins) in a single JavaScript file
    • The actions may match a structure which the server expects to call some functions: initializing, item-pressed...
    • As the actions are Javascript files, you can use the vast library from npm
  • Load the actions to run at startup from a directory. Making them interchangeable/hackable.

I will dig in the server, actions and client.

Server side

These are the core concepts of the app:

  • Layout: Bunch of items
  • Item: An element that has a single or multiple states. It is clickable in the client.
  • State: Definition of the item status: text, textColor, bgColor, icon and an action list.
  • Action: Action which will be fired (can be more than one in a state) in the host computer when the item is pressed in the client.

The server is a simple app which reads a JSON file which defines the layout. The work of the server is to manage the current directory, send the needed information to show in the client. And when an item is clicked in the client, the servers runs the actions attached to that item or sets the directory to show. This server-client communication is done by Websockets.

The server directory tree looks like this

|-- ideckia         -> the app executable
|-- app.props       -> properties for the server (actions directory path, layout file path, log level, listening port...)
|-- layout.json     -> the layout information
|-+ actions         -> directory where the actions are stored
Enter fullscreen mode Exit fullscreen mode

The layout can be edited by hand, but the server provides an integrated editor to edit your layout. Open the browser and go to http://localhost:8888/editor (the port is the one where the server is running). I know it is not the prettiest thing, but it does get the job done.

Now we'll see how are the actions internals.

Actions

Actions sources are available in the actions folder usually (configurable via app.props file next to the executable). Every action is defined in it's own folder and an index.js file in it.

|-- ideckia
|-- app.props
|-- layout.json
|-- actions
|   |-- my_action
|       |-- index.js
|   |-- another_action
|       |-- index.js
|       |-- dependencies.js
|       |-+ node_modules
Enter fullscreen mode Exit fullscreen mode

This index.js file must have this functions defined to be called from the server when loaded and executed:

  • setup(props, server):Void
    • Server will call to this method to inject the configuration properties of the action instance and some convenient functions from the server.
  • init(initialState:ItemState):Promise
    • The server will call to this once, to initialize what you need
  • execute(currentState:ItemState):Promise
    • The server will call when the associated item is clicked.
  • onLongPress(currentState:ItemState):Promise
    • The server will call when the associated item is long pressed.
  • getActionDescriptor():ActionDescriptor
    • This method is used by the editor.

There are some default actions that comes in the default ideckia package:

  • Command: Execute an application or shell file with given parameters
  • Keyboard: Create hotkeys, write strings... A wrapper for NutJs
  • Counter: Count how many times the item is clicked. Can be a countdown too.
  • Random color: Generate random color and show it in the item.
  • Stopwatch: Executing this action, will start and pause a timer shown in the button itself.
  • Timezones: Show the time in the configurated timezones.
  • Worklog: Log you daily work in a plain json file.
  • FTP-Connect: Connect to FTP in a simple and fast way.
  • SSH-Connect: Connect to SSH in a simple and fast way.
  • Open weather: Show the weather in the configured towns.
  • Clementine control: Control Clementine.
  • Mute mic: Mute / unmute microphone.
  • Toot: Publish a toot in mastodon.
  • Wait: Waits given milliseconds until the next action.
  • Countdown: Countdown timer
  • Log-in: Writes username and password and presses 'Enter' (this action uses Keyboard, it is mandatory).
  • Color-picker: Show in the item the color of the pixel where the mouse is.
  • Obs-control: Control OBS Studio (replacing former obs-websocket action)
  • KeePasXC: Get write the username and password from KeePassXC. This action uses Log-in, it is mandatory.
  • Emoji: Shows a random emoji every time is clicked

Client

The server sends the panel information to any connected client. And those clients send to the server which item has been clicked. There is a mobile client written in Flutter.

What I've achieved

  • Cross-platform application (windows, mac and linux)
  • Portable (no installation needed)
    • Use PKG to create a single executable
    • light executable < 40MB
  • modular and hackable
    • Any action can be changed
    • The editor can be easily stylized
  • All the layout info in a plain json file
  • Tons of NPM packages usable
  • Easy to create and test new actions

More info here

💖 💪 🙅 🚩
josuigoa
Josu Igoa

Posted on February 16, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Open source StreamDeck alternative
productivity Open source StreamDeck alternative

February 16, 2023