Closed evilC closed 5 years ago
It does.
You can open as many devices as you like and use them at the same time. You can use StreamDeck.EnumerateDevices
to get all connected devices. This method will return an enumerable of IDeviceReferenceHandle
and you can retrieve a device handle (to control the deck) with the .Open()
method
Here is a quick example (not very pretty) to demonstrate how to use multiple devices at once.
using OpenMacroBoard.SDK;
using StreamDeckSharp;
using System;
using System.Linq;
using System.Threading;
namespace StreamDeckMultipleTest
{
class Program
{
static void Main(string[] args)
{
//get all devices (and open them)
var allConnectedDevices = StreamDeck
.EnumerateDevices()
.Select(x => x.Open())
.ToList();
//generate a random color key
var rnd = new Random();
var color = new byte[3];
rnd.NextBytes(color);
var rndKey = KeyBitmap.Create.FromRgb(color[0], color[1], color[2]);
//use all opened devices (at the same time)
foreach(var d in allConnectedDevices)
{
d.SetKeyBitmap(rndKey);
}
//do other stuff with open devices...
Thread.Sleep(5000);
//Close all devices
foreach (var d in allConnectedDevices)
d.Dispose();
}
}
}
Let me know if you need more help ;-)
Cheers, will look into porting over to your version then.
FYI, your README seems wrong.
var deck = StreamDeck.FromHID()
/ deck.KeyPressed += KeyHandler
OK, so acquiring the device does not seem a problem, but I am having trouble working out how to port over some of the other functionality:
BTW, if you want to avoid back-and-forth on your issue tracker, I can be found in the HidWizards Discord
PS, I just noticed your OpenMacroBoard comments. I am part of a project called UCR.
The main reason I bought an SD was purely to investigate how I might integrate devices such as this into UCR - AutoHotStreamDeck is just a side project, to get a bit of experience with the device.
If you are at all interested, you would be welcome joining us in trying to integrate support for Macro Boards into UCR!
Regarding build errors. You can create KeyBitmaps
with the KeyBitmap.Create
factory.
A few examples:
KeyBitmap.Create.FromWpfElement(width, height, canvas);
KeyBitmap.Create.FromGraphics(width, height, g =>
{
g.DrawEllipse(...);
g.DrawLine(...);
g.DrawString(...);
});
KeyBitmap.Create.FromRgb(255, 0, 0);
You can get the number of keys for an IMarcoBoard
with device.Keys.Count
Sorry wiki and readme is pretty outdated at the moment (see issue #8)
PS: If you want to integrate StreamDecks into UCR I would recommend to link OpenMacroBoard, this way UCR would automatically support other LCD boards that implement IMacroBoard.
If you have team members without a real stream deck you can use a "virtual board/streamdeck" as described here: OpenMacroBoard-Core / Getting started for development.
So I can use one real SD plus one virtual MacroBoard to test my multiple device code?
Otherwise, seems like that covers all my questions except how to discover the resolution of the screens for a given device.
I am quite busy over the next couple of days, so it may be a while before I get to work on it again.
So I can use one real SD plus one virtual MacroBoard to test my multiple device code? Yes. You could even use multiple virtual boards if you want.
On every device (IMacroBoard
) you can use the Keys Collection to get the exact layout and dimensions. OpenMacroBoard even supports "weird" (non-grid) layouts like keyboards.
Thanks for that, with those pointers I managed to port pretty much everything over - https://github.com/evilC/AutoHotStreamDeck/tree/feature/openmacroboard
However, my demo AHK script tries to work out how many columns and rows there are, and I don't see a way to work that out without examining rects etc.
I also don't see a way of getting eg VID/PID of the device, so I can't make a lookup table.
SharpLibStreamDeck had RowCount
and ColumnCount
properties - I know these maybe don't make sense in a non-grid scenario, but by going more generic we are maybe losing out on simplicity?
WRT the virtualboard, it does not quite seem to do what I want in this case - when I run the demo code in a console app, then start my main app and call EnumerateDevices
, I still only see my real SD. I was hoping to see the virtual device also.
If it was possible to have one process spawn a virtualboard that another process could read it as if it were a real one, that could also potentially open up a bunch of interesting use-cases. I do work with disabled people, and a virtualboard could potentially act as a virtual on-screen keyboard on steroids, without the need for a dedicated API.
People who only used their eyes to look at an icon and blink could use an on screen virtualboard along with something like a Tobii Eye Tracker to click the buttons, people who can only operate a limited number of buttons can use a physical MacroBoard.
If we could allow both of those via one unified API, that would be really cool.
I dunno how you could get a virtual board to be visible to EnumerateDevices
- one way of course would be HID emulation, which as it happens, I know just the man - Nefarius has a generic virtual USB bus that could do it, but maybe there's a simpler way? I suppose UCR could spawn the virtualboards also, but that would add some extra complexity (In terms of configuring number and size of buttons etc).
tries to work out how many columns and rows there are There is no (general) method of determining how many rows and colums a device has (at the moment) because the library also allows non-grid-layouts (like keyboards for example)
I also don't see a way of getting eg VID/PID of the device The library is also agnostic about how a device is connected. VID and PID are USB specific. For example the virtual stream deck does not have a VID or PID because it's not a USB device. I think about implementing some other form of identification (GUID like key derived from device specific paramters)
but by going more generic we are maybe losing out on simplicity? That's true - I'm open for suggestions (that don't sacrifice non-grid layout support)
I was hoping to see the virtual device also.
EnumerateDevices
is a method of the StreamDeckSharp package and only enumerates StreamDeck hardware. You can use BoardFactory.SpawnVirtualBoard()
from the OpenMacroBoard.VirtualBoard
package. Atm there is no common enumerator, but I already thought about implementing some kind of Provider Interface and a common enumeration method that invokes all providers.
If it was possible to have one process spawn a virtualboard that another process could read it as if it were a real one, that could also potentially open up a bunch of interesting use-cases That was the original idea for the virtual board but at the end I was a bit to lazy ;-) (but still on my todo list)
I dunno how you could get a virtual board to be visible to EnumerateDevices
I wouldn't make it visible to EnumerateDevices because that's StreamDeck specific. I would write an IBoardProvider
with a method that allows to enumerate devices. All Providers (StreamDeckSharp, VirtualBoard, etc.) implement IBoardProvider
.
The OpenMacroBoard core will look for IBoardProviders on startup (get all types that implement IBoardProvider
via reflection) and provide a method to enumerate boards that would list all devices from different providers.
It looks like the ctors for the KeyPositionCollection accept xCount and yCount params. Why not expose these as properties?
I get that IKeyPositionCollection
is intended to be able to represent both grid and non-grid layouts, but hiding useful information that is being passed in is counter-productive. Could you not have IGridKeyPositionCollection
and INonGridKeyPositionCollection
or something?
I bodged it for now and just assumed a 6-button device was a 3x2 mini and a 15-button devices was a 5x3 SD
@evilC I'm working on that atm. Should be done by the weekend.
Awesome, thank you!
Just updated StreamDeckSharp to v0.3.0 (https://www.nuget.org/packages/streamdecksharp/) and the Keys property now returns a GridKeyPositionCollection
.
Quick Example:
using (var deck = StreamDeck.OpenDevice())
{
Console.WriteLine($"Number of Keys horizontally : {deck.Keys.KeyCountX}");
Console.WriteLine($"Number of Keys vertically : {deck.Keys.KeyCountY}");
// there are also Properties for
// - distance between keys (x and y)
// - key size (x and y)
}
Let me know what you think.
I released some test builds yesterday with support for multiple SDs.
I had to make some changes - targetting IStreamDeckBoard
instead of IMacroBoard
, but I am unsure if this could actually be done via the generic library.
I am waiting for feedback as to whether it all works or not, as I cannot test myself.
You could use a VirtualBoard for testing and cast Keys to IGridKeyPositionCollection
.
I can test the KeyCount props, they work fine.
What I am unable to test is multiple StreamDecks connected at once, and whether StreamDeck.EnumerateDevices()
and associated code works OK.
I seem to remember we discussed this before, and VirtualBoards are not visible to EnumerateDevices?
You can spawn multiple VirtualBoards if you want. I plan on writing a unified provider interface but I'm not sure when that will be ready.
No rush, the people requesting it seem to have gone quiet anyway
Hi, I currently use the Slion/SharpLibStreamDeck library for my AutoHotStreamDeck library.
I am wondering if your library could possibly support multiple StreamDecks?