Skip to content

Commit 977413d

Browse files
Stefan Schubertmalaupa
authored andcommitted
add SetMustMany
* to set many properties at once and to emit only one signal
1 parent 6cc540d commit 977413d

File tree

2 files changed

+118
-22
lines changed

2 files changed

+118
-22
lines changed

prop/prop.go

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -278,32 +278,40 @@ func (p *Properties) Introspection(iface string) []introspect.Property {
278278

279279
// set sets the given property and emits PropertyChanged if appropriate. p.mut
280280
// must already be locked.
281-
func (p *Properties) set(iface, property string, v interface{}) error {
282-
prop := p.m[iface][property]
283-
err := dbus.Store([]interface{}{v}, prop.Value)
281+
func (p *Properties) set(iface string, properties []string, v ...interface{}) error {
282+
var props []interface{}
283+
for _, property := range properties {
284+
props = append(props, p.m[iface][property].Value)
285+
}
286+
err := dbus.Store(v, props...)
284287
if err != nil {
285288
return err
286289
}
287-
return p.emitChange(iface, property)
290+
return p.emitChange(iface, properties...)
288291
}
289292

290-
func (p *Properties) emitChange(iface, property string) error {
291-
prop := p.m[iface][property]
292-
switch prop.Emit {
293-
case EmitFalse:
294-
return nil // do nothing
295-
case EmitInvalidates:
296-
return p.conn.Emit(p.path, "org.freedesktop.DBus.Properties.PropertiesChanged",
297-
iface, map[string]dbus.Variant{}, []string{property})
298-
case EmitTrue:
299-
return p.conn.Emit(p.path, "org.freedesktop.DBus.Properties.PropertiesChanged",
300-
iface, map[string]dbus.Variant{property: dbus.MakeVariant(prop.Value)},
301-
[]string{})
302-
case EmitConst:
303-
return nil
304-
default:
305-
panic("invalid value for EmitType")
293+
func (p *Properties) emitChange(iface string, properties ...string) error {
294+
changes := make(map[string]dbus.Variant)
295+
invalidates := []string{}
296+
297+
for _, property := range properties {
298+
prop := p.m[iface][property]
299+
switch prop.Emit {
300+
case EmitFalse:
301+
return nil // do nothing
302+
case EmitInvalidates:
303+
invalidates = append(invalidates, property)
304+
case EmitTrue:
305+
changes[property] = dbus.MakeVariant(prop.Value)
306+
case EmitConst:
307+
return nil
308+
default:
309+
panic("invalid value for EmitType")
310+
}
306311
}
312+
313+
return p.conn.Emit(p.path, "org.freedesktop.DBus.Properties.PropertiesChanged",
314+
iface, changes, invalidates)
307315
}
308316

309317
// Set implements org.freedesktop.Properties.Set.
@@ -330,7 +338,7 @@ func (p *Properties) Set(iface, property string, newv dbus.Variant) *dbus.Error
330338
return err
331339
}
332340
}
333-
if err := p.set(iface, property, newv.Value()); err != nil {
341+
if err := p.set(iface, []string{property}, newv.Value()); err != nil {
334342
return dbus.MakeFailedError(err)
335343
}
336344
return nil
@@ -341,7 +349,25 @@ func (p *Properties) Set(iface, property string, newv dbus.Variant) *dbus.Error
341349
func (p *Properties) SetMust(iface, property string, v interface{}) {
342350
p.mut.Lock()
343351
defer p.mut.Unlock() // unlock in case of panic
344-
err := p.set(iface, property, v)
352+
err := p.set(iface, []string{property}, v)
353+
if err != nil {
354+
panic(err)
355+
}
356+
}
357+
358+
// SetMustMany sets the values of the given property value map and panics if any interface or
359+
// property name are invalid.
360+
func (p *Properties) SetMustMany(iface string, newValues map[string]interface{}) {
361+
p.mut.Lock()
362+
defer p.mut.Unlock()
363+
364+
properties := make([]string, 0, len(newValues))
365+
values := make([]interface{}, 0, len(newValues))
366+
for key, val := range newValues {
367+
properties = append(properties, key)
368+
values = append(values, val)
369+
}
370+
err := p.set(iface, properties, values...)
345371
if err != nil {
346372
panic(err)
347373
}

prop/prop_test.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,73 @@ func TestInt32(t *testing.T) {
159159
t.Errorf("expected r to be int32(101), but was %#v", r)
160160
}
161161
}
162+
163+
func TestMany(t *testing.T) {
164+
srv, err := dbus.SessionBus()
165+
if err != nil {
166+
t.Fatal(err)
167+
}
168+
defer srv.Close()
169+
170+
cli, err := dbus.SessionBus()
171+
if err != nil {
172+
t.Fatal(err)
173+
}
174+
defer cli.Close()
175+
176+
propsSpec := map[string]map[string]*Prop{
177+
"org.guelfey.DBus.Test": {
178+
"one": {
179+
"oneValue",
180+
true,
181+
EmitTrue,
182+
nil,
183+
},
184+
"two": {
185+
0,
186+
true,
187+
EmitInvalidates,
188+
nil,
189+
},
190+
},
191+
}
192+
props := New(srv, "/org/guelfey/DBus/Test", propsSpec)
193+
194+
r := props.GetMust("org.guelfey.DBus.Test", "one")
195+
if r != "oneValue" {
196+
t.Errorf("expected r to be 'oneValue', but was %#v", r)
197+
}
198+
r = props.GetMust("org.guelfey.DBus.Test", "two")
199+
if r != 0 {
200+
t.Errorf("expected r to be 0, but was %#v", r)
201+
}
202+
203+
ready := make(chan struct{})
204+
c := make(chan *dbus.Signal, 1)
205+
go func() {
206+
cli.AddMatchSignal(dbus.WithMatchMember("PropertiesChanged"))
207+
defer cli.RemoveMatchSignal(dbus.WithMatchMember("PropertiesChanged"))
208+
209+
cli.Signal(c)
210+
close(ready)
211+
for sig := range c {
212+
if sig.Name == "org.freedesktop.DBus.Properties.PropertiesChanged" {
213+
c <- sig
214+
}
215+
}
216+
}()
217+
218+
<-ready
219+
props.SetMustMany("org.guelfey.DBus.Test", map[string]interface{}{"one": "otherValue", "two": 1})
220+
sig := <-c
221+
222+
changed := sig.Body[1].(map[string]dbus.Variant)
223+
invalidated := sig.Body[2].([]string)
224+
if len(changed) != 1 || len(invalidated) != 1 {
225+
t.Fatalf("changed len or invalidated len mismatch")
226+
}
227+
if changed["one"].Value() != "otherValue" {
228+
t.Fatalf("changed value mismatch")
229+
}
230+
231+
}

0 commit comments

Comments
 (0)