Skip to content

Commit c86326a

Browse files
committed
Clean up
Adjustments to how the arduino code works Better describe the config file
1 parent e11baf1 commit c86326a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+109
-3098
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ releases/
1212
*.bin
1313
logs/
1414
preferences.yaml
15+
arduino/**/*.hex
16+

arduino/deej-5-sliders-vanilla/deej-5-sliders-vanilla.ino

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,8 @@
11
const int NUM_SLIDERS = 5;
22
const int sensor_history = 5;
3-
const int slider_range = 2;
4-
const int analogInputs[NUM_SLIDERS] = {A0, A1, A2, A3, A10};
5-
int lastValues[NUM_SLIDERS][sensor_history] = {
6-
{0,0,0,0,0},
7-
{0,0,0,0,0},
8-
{0,0,0,0,0},
9-
{0,0,0,0,0},
10-
{0,0,0,0,0}};
3+
const int slider_range = 4;
4+
const int analogInputs[NUM_SLIDERS] = {A0, A10, A1, A2, A3};
5+
int (*lastValues)[NUM_SLIDERS] = new int[sensor_history][NUM_SLIDERS];
116
String last_string = "";
127

138
int analogSliderValues[NUM_SLIDERS];
@@ -22,14 +17,15 @@ void setup() {
2217

2318
void loop() {
2419
updateSliderValues();
25-
sendSliderValues(); // Actually send data (all the time)
20+
sendSliderValues();
2621
// printSliderValues(); // For debug
2722
delay(1);
2823
}
2924

3025
void updateSliderValues() {
3126
int current_value = 0;
3227
for (int i = 0; i < NUM_SLIDERS; i++) {
28+
current_value = analogRead(analogInputs[i]);
3329
current_value = analogRead(analogInputs[i]);
3430
int updateOutput = 1;
3531
for(int ii = 0 ; ii<sensor_history ; ii++ ){

assets/build-3d-annotated.png

-750 KB
Binary file not shown.

assets/build-3d.png

-729 KB
Binary file not shown.

assets/build-shoebox.jpg

-256 KB
Binary file not shown.
-141 KB
Binary file not shown.

assets/community-builds/aithorn.jpg

-79.8 KB
Binary file not shown.

assets/community-builds/bao.jpg

-297 KB
Binary file not shown.

assets/community-builds/bgrier.jpg

-483 KB
Binary file not shown.

assets/community-builds/bupher.jpg

-278 KB
Binary file not shown.
-119 KB
Binary file not shown.
-523 KB
Binary file not shown.

assets/community-builds/daggr.jpg

-402 KB
Binary file not shown.

assets/community-builds/dimitar.jpg

-280 KB
Binary file not shown.
-554 KB
Binary file not shown.
Binary file not shown.

assets/community-builds/extra/dimitar-schematic.sch

Lines changed: 0 additions & 3004 deletions
This file was deleted.
-546 KB
Binary file not shown.
-441 KB
Binary file not shown.

assets/community-builds/ginjah.jpg

-460 KB
Binary file not shown.
-469 KB
Binary file not shown.
Binary file not shown.
-373 KB
Binary file not shown.

assets/community-builds/kawaru86.jpg

-93.6 KB
Binary file not shown.

assets/community-builds/marcioasf.jpg

-367 KB
Binary file not shown.

assets/community-builds/max.jpg

-310 KB
Binary file not shown.

assets/community-builds/mozza.jpg

-200 KB
Binary file not shown.

assets/community-builds/mozzav2.jpg

-333 KB
Binary file not shown.
-248 KB
Binary file not shown.

assets/community-builds/ocyrus99.jpg

-349 KB
Binary file not shown.

assets/community-builds/olijoe.jpg

-423 KB
Binary file not shown.

assets/community-builds/omnisai.jpg

-276 KB
Binary file not shown.

assets/community-builds/optagon.jpg

-310 KB
Binary file not shown.

assets/community-builds/probird.jpg

-268 KB
Binary file not shown.

assets/community-builds/scotte.jpg

-243 KB
Binary file not shown.

assets/community-builds/snackya.jpg

-208 KB
Binary file not shown.
-471 KB
Binary file not shown.

assets/community-builds/snow.jpg

-229 KB
Binary file not shown.
-584 KB
Binary file not shown.
-158 KB
Binary file not shown.

assets/community-builds/tpo.jpg

-915 KB
Binary file not shown.

assets/community-builds/wshaf.jpg

-194 KB
Binary file not shown.

assets/community-builds/yamoef.jpg

-386 KB
Binary file not shown.

assets/logo-512.png

-25.9 KB
Binary file not shown.

assets/logo.svg

Lines changed: 0 additions & 1 deletion
This file was deleted.

assets/schematic.png

-110 KB
Binary file not shown.

config.yaml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
# process names are case-insensitive
1+
# process names are case-insensitive but also require the application binary name to match correctly. eg, ${process_binary}: ${proccess_name}
2+
# device names are case-sensitive and are in the format: reeemiks.device: ${device_name}~${pipewire_node_name}
3+
# If you can't get the name correct then running in verbose mode will print all the applications and the devices (called sinks) reeemiks can find.
24
# you can use 'master' to indicate the master channel, or a list of process names to create a group
35
# you can use 'mic' to control your mic input level (uses the default recording device)
4-
# you can use 'deej.unmapped' to control all apps that aren't bound to any slider (this ignores master, system, mic and device-targeting sessions)
5-
# windows only - you can use 'deej.current' to control the currently active app (whether full-screen or not)
6-
# windows only - you can use a device's full name, i.e. "Speakers (Realtek High Definition Audio)", to bind it. this works for both output and input devices
7-
# windows only - you can use 'system' to control the "system sounds" volume
6+
# you can use 'reeemiks.unmapped' to control all apps that aren't bound to any slider (this ignores master, system, mic and device-targeting sessions)
87
# important: slider or knob indexes start at 0, regardless of which analog pins you're using!
98
slider_mapping:
109
0:

deej.sh

Lines changed: 0 additions & 4 deletions
This file was deleted.

go.mod

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ require (
1010
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 // indirect
1111
github.com/jacobsa/go-serial v0.0.0-20180131005756-15cf729a72d4
1212
github.com/jfreymuth/pulse v0.0.0-20200608153616-84b2d752b9d4
13-
github.com/kirsle/configdir v0.0.0-20170128060238-e45d2f54772f // indirect
13+
github.com/kirsle/configdir v0.0.0-20170128060238-e45d2f54772f
1414
github.com/lxn/win v0.0.0-20191128105842-2da648fda5b4
15-
github.com/micmonay/keybd_event v1.1.1 // indirect
15+
github.com/micmonay/keybd_event v1.1.1
1616
github.com/mitchellh/go-ps v1.0.0
1717
github.com/moutend/go-wca v0.1.2-0.20190422112502-0fa027b3d89a
1818
github.com/spf13/viper v1.7.1
19-
github.com/sstallion/go-hid v0.14.1 // indirect
19+
github.com/sstallion/go-hid v0.14.1
2020
github.com/thoas/go-funk v0.7.0
2121
go.uber.org/zap v1.15.0
2222
)

go.sum

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,6 @@ github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
197197
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
198198
github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
199199
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
200-
github.com/sstallion/go-hid v0.0.0-20190621001400-1cf4630be9f4 h1:hczfXYN39SDj4FcN5J7sgHBtJm4U7ef2nvlonn6NvVU=
201-
github.com/sstallion/go-hid v0.0.0-20190621001400-1cf4630be9f4/go.mod h1:JwBz6izP5UGcbYDU5VGeLkqpRIpSBDPtCB5/XnVXz9Q=
202200
github.com/sstallion/go-hid v0.14.1 h1:shbZlKqv5fr1KnxwqtLEPGkOoA6OSUWTx9TblegATvc=
203201
github.com/sstallion/go-hid v0.14.1/go.mod h1:fPKp4rqx0xuoTV94gwKojsPG++KNKhxuU88goGuGM7I=
204202
github.com/sstallion/go-tools v1.0.1/go.mod h1:y3Rklut4T6cPLmNkaU0obckQpnVSSvAZlB2N87qgUtg=
@@ -294,7 +292,6 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w
294292
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
295293
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
296294
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
297-
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9 h1:YTzHMGlqJu67/uEo1lBv0n3wBXhXNeUbB1XfN2vmTm0=
298295
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
299296
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
300297
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

pkg/deej/config.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ type CanonicalConfig struct {
3333
}
3434

3535
EnableHidListen bool
36-
3736
InvertSliders bool
38-
3937
NoiseReductionLevel string
4038

39+
ReeemiksMatching string
40+
4141
logger *zap.SugaredLogger
4242
notifier Notifier
4343
stopWatcherChannel chan bool
@@ -65,6 +65,7 @@ const (
6565
configKeyUsagePage = "usage_page"
6666
configKeyUsage = "usage"
6767
configKeyEnableHID = "enable_hid_listen"
68+
configReeemiksMatching = "Reeemiks.matching"
6869

6970
defaultCOMPort = "COM4"
7071
defaultBaudRate = 9600
@@ -90,7 +91,7 @@ var userConfigPath = func() string {
9091
if !xdg_exists && rel_exists {
9192
util.MoveFile(userConfigFilename,configFile)
9293
} else if xdg_exists && rel_exists {
93-
fmt.Printf("I'm ignoring your config relative to my binary, your config is located at: %s", configFile)
94+
fmt.Printf("WARN: I'm ignoring your config relative to my binary, your config is located at: %s\n", configFile)
9495
} else if !xdg_exists && !rel_exists {
9596
fmt.Errorf("Config file doesn't exist: %s", configFile)
9697
}
@@ -132,6 +133,7 @@ func NewConfig(logger *zap.SugaredLogger, notifier Notifier) (*CanonicalConfig,
132133
userConfig.SetDefault(configKeyCOMPort, defaultCOMPort)
133134
userConfig.SetDefault(configKeyBaudRate, defaultBaudRate)
134135
userConfig.SetDefault(configKeyEnableHID, false)
136+
userConfig.SetDefault(configReeemiksMatching, map[string]string{})
135137

136138
internalConfig := viper.New()
137139
internalConfig.SetConfigName(internalConfigName)
@@ -291,6 +293,8 @@ func (cc *CanonicalConfig) populateFromVipers() error {
291293
cc.InvertSliders = cc.userConfig.GetBool(configKeyInvertSliders)
292294
cc.NoiseReductionLevel = cc.userConfig.GetString(configKeyNoiseReductionLevel)
293295

296+
cc.ReeemiksMatching = cc.userConfig.GetString(configReeemiksMatching)
297+
294298
cc.logger.Debug("Populated config fields from vipers")
295299

296300
return nil

pkg/deej/deej.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func NewDeej(logger *zap.SugaredLogger, verbose bool) (*Deej, error) {
5555
verbose: verbose,
5656
}
5757

58-
sessionFinder, err := newSessionFinder(logger)
58+
sessionFinder, err := newSessionFinder(logger,config)
5959
if err != nil {
6060
logger.Errorw("Failed to create SessionFinder", "error", err)
6161
return nil, fmt.Errorf("create new SessionFinder: %w", err)

pkg/deej/session_finder_linux.go

Lines changed: 81 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ import (
1212
type paSessionFinder struct {
1313
logger *zap.SugaredLogger
1414
sessionLogger *zap.SugaredLogger
15+
config *CanonicalConfig
1516

1617
client *proto.Client
1718
conn net.Conn
1819
}
1920

20-
func newSessionFinder(logger *zap.SugaredLogger) (SessionFinder, error) {
21+
func newSessionFinder(logger *zap.SugaredLogger, config *CanonicalConfig) (SessionFinder, error) {
2122
client, conn, err := proto.Connect("")
2223
if err != nil {
2324
logger.Warnw("Failed to establish PulseAudio connection", "error", err)
@@ -26,7 +27,7 @@ func newSessionFinder(logger *zap.SugaredLogger) (SessionFinder, error) {
2627

2728
request := proto.SetClientName{
2829
Props: proto.PropList{
29-
"application.name": proto.PropListString("deej"),
30+
"application.name": proto.PropListString("Reeemiks"),
3031
},
3132
}
3233
reply := proto.SetClientNameReply{}
@@ -38,6 +39,7 @@ func newSessionFinder(logger *zap.SugaredLogger) (SessionFinder, error) {
3839
sf := &paSessionFinder{
3940
logger: logger.Named("session_finder"),
4041
sessionLogger: logger.Named("sessions"),
42+
config: config,
4143
client: client,
4244
conn: conn,
4345
}
@@ -129,11 +131,28 @@ func (sf *paSessionFinder) enumerateAndAddSessions(sessions *[]Session) error {
129131
return fmt.Errorf("get sink input list: %w", err)
130132
}
131133

132-
for _, info := range reply {
133-
var process_binary proto.PropListEntry
134-
var process_name proto.PropListEntry
135-
var name string
136-
var ok bool
134+
if sf.config.ReeemiksMatching == "default" {
135+
for _, info := range reply {
136+
name, ok := info.Properties["application.process.binary"]
137+
138+
if !ok {
139+
sf.logger.Warnw("Failed to get sink input's process name", "sinkInputIndex", info.SinkInputIndex)
140+
continue
141+
}
142+
143+
// create the deej session object
144+
newSession := newPASession(sf.sessionLogger, sf.client, info.SinkInputIndex, info.Channels, name.String())
145+
146+
// add it to our slice
147+
*sessions = append(*sessions, newSession)
148+
149+
}
150+
} else { // All new Reeemiks features
151+
for _, info := range reply {
152+
var process_binary proto.PropListEntry
153+
var process_name proto.PropListEntry
154+
var name string
155+
var ok bool
137156

138157
process_binary, ok = info.Properties["media.name"]
139158
if !ok {
@@ -147,69 +166,70 @@ func (sf *paSessionFinder) enumerateAndAddSessions(sessions *[]Session) error {
147166
}
148167
name = process_binary.String() + ": " + process_name.String()
149168

150-
sf.logger.Debug("Process: ", name)
151-
152-
// create the deej session object
153-
newSession := newPASession(sf.sessionLogger, sf.client, info.SinkInputIndex, info.Channels, name)
169+
sf.logger.Info("Process: ", name)
154170

155-
// add it to our slice
156-
*sessions = append(*sessions, newSession)
171+
// create the deej session object
172+
newSession := newPASession(sf.sessionLogger, sf.client, info.SinkInputIndex, info.Channels, name)
157173

158-
}
174+
// add it to our slice
175+
*sessions = append(*sessions, newSession)
159176

160-
request2 := proto.GetSinkInfoList{}
161-
reply2 := proto.GetSinkInfoListReply{}
177+
}
162178

163-
if err := sf.client.Request(&request2, &reply2); err != nil {
164-
sf.logger.Warnw("Failed to get sink list", "error", err)
165-
return fmt.Errorf("get sink list: %w", err)
166-
}
179+
request2 := proto.GetSinkInfoList{}
180+
reply2 := proto.GetSinkInfoListReply{}
167181

168-
for _, info := range reply2 {
169-
var audio_pos proto.PropListEntry
170-
var process_binary proto.PropListEntry
171-
var process_name proto.PropListEntry
172-
var name string
173-
var ok bool
182+
if err := sf.client.Request(&request2, &reply2); err != nil {
183+
sf.logger.Warnw("Failed to get sink list", "error", err)
184+
return fmt.Errorf("get sink list: %w", err)
185+
}
174186

175-
audio_pos, ok = info.Properties["audio.position"]
176-
if ok {
177-
process_binary, ok = info.Properties["media.name"]
178-
audio_pos = audio_pos
179-
if !ok {
180-
sf.logger.Debug("Failed to get sink's media name", "sinkInputIndex", info.SinkIndex)
181-
continue
187+
for _, info := range reply2 {
188+
var audio_pos proto.PropListEntry
189+
var process_binary proto.PropListEntry
190+
var process_name proto.PropListEntry
191+
var name string
192+
var ok bool
193+
194+
audio_pos, ok = info.Properties["audio.position"]
195+
if ok {
196+
audio_pos = audio_pos
197+
process_binary, ok = info.Properties["media.name"]
198+
if !ok {
199+
sf.logger.Debug("Failed to get sink's media name", "sinkInputIndex", info.SinkIndex)
200+
continue
201+
}
202+
process_name, ok = info.Properties["node.name"]
203+
if !ok {
204+
sf.logger.Debug("Failed to get sink's node name", "sinkInputIndex", info.SinkIndex)
205+
continue
206+
}
207+
// name = "deej.device: " + process_name.String()
208+
name = "reeemiks.device: " + process_binary.String() + "~" + process_name.String()
182209
}
183-
process_name, ok = info.Properties["node.name"]
184-
if !ok {
185-
sf.logger.Debug("Failed to get sink's node name", "sinkInputIndex", info.SinkIndex)
186-
continue
210+
211+
// regex_match, err := regexp.MatchString("^(Audio/(Device|Sink|Source)|Stream/Output/Audio)$", media_class.String())
212+
// if err==nil {
213+
// if regex_match {
214+
// } else {
215+
// }
216+
// } else {
217+
// if !ok {
218+
// sf.logger.Warnw("Failed to regex match sink input's media class", "sinkInputIndex", info.SinkIndex)
219+
// continue
220+
// }
221+
// }
222+
223+
if name != "" {
224+
sf.logger.Info("Sink: ", name)
225+
226+
// create the deej session object
227+
newSession := newPASession(sf.sessionLogger, sf.client, info.SinkIndex, info.Channels, name)
228+
229+
// add it to our slice
230+
*sessions = append(*sessions, newSession)
187231
}
188-
// name = "deej.device: " + process_name.String()
189-
name = "reeemiks.device: " + process_binary.String() + "~" + process_name.String()
190232
}
191-
192-
// regex_match, err := regexp.MatchString("^(Audio/(Device|Sink|Source)|Stream/Output/Audio)$", media_class.String())
193-
// if err==nil {
194-
// if regex_match {
195-
// } else {
196-
// }
197-
// } else {
198-
// if !ok {
199-
// sf.logger.Warnw("Failed to regex match sink input's media class", "sinkInputIndex", info.SinkIndex)
200-
// continue
201-
// }
202-
// }
203-
204-
205-
sf.logger.Debug("Sink: ", name)
206-
207-
// create the deej session object
208-
newSession := newPASession(sf.sessionLogger, sf.client, info.SinkIndex, info.Channels, name)
209-
210-
// add it to our slice
211-
*sessions = append(*sessions, newSession)
212-
213233
}
214234

215235
return nil

pkg/deej/session_finder_windows.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
type wcaSessionFinder struct {
1717
logger *zap.SugaredLogger
1818
sessionLogger *zap.SugaredLogger
19+
config *CanonicalConfig
1920

2021
eventCtx *ole.GUID // needed for some session actions to successfully notify other audio consumers
2122

@@ -31,8 +32,8 @@ type wcaSessionFinder struct {
3132

3233
const (
3334

34-
// there's no real mystery here, it's just a random GUID
35-
myteriousGUID = "{1ec920a1-7db8-44ba-9779-e5d28ed9f330}"
35+
// random GUID, used for the application's GUID
36+
reeemiksGUID = "{e3f979e1-2f34-4a52-9d2c-0375ea389a1f}"
3637

3738
// the notification client will call this multiple times in quick succession based on the
3839
// default device's assigned media roles, so we need to filter out the extraneous calls
@@ -42,11 +43,12 @@ const (
4243
deviceSessionFormat = "device.%s"
4344
)
4445

45-
func newSessionFinder(logger *zap.SugaredLogger) (SessionFinder, error) {
46+
func newSessionFinder(logger *zap.SugaredLogger, config *CanonicalConfig) (SessionFinder, error) {
4647
sf := &wcaSessionFinder{
4748
logger: logger.Named("session_finder"),
4849
sessionLogger: logger.Named("sessions"),
49-
eventCtx: ole.NewGUID(myteriousGUID),
50+
eventCtx: ole.NewGUID(reeemiksGUID),
51+
config: config,
5052
}
5153

5254
sf.logger.Debug("Created WCA session finder instance")

0 commit comments

Comments
 (0)