aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/pipewire/client.go
blob: 96beeba3816a955a9176ca6cf8b2e23ada8cda48 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package pipewire

/* pipewire/client.h */

const (
	PW_TYPE_INTERFACE_Client = PW_TYPE_INFO_INTERFACE_BASE + "Client"
	PW_CLIENT_PERM_MASK      = PW_PERM_RWXM
	PW_VERSION_CLIENT        = 3

	PW_ID_CLIENT = 1
)

const (
	PW_CLIENT_CHANGE_MASK_PROPS = 1 << iota

	PW_CLIENT_CHANGE_MASK_ALL = 1<<iota - 1
)

const (
	PW_CLIENT_EVENT_INFO = iota
	PW_CLIENT_EVENT_PERMISSIONS
	PW_CLIENT_EVENT_NUM

	PW_VERSION_CLIENT_EVENTS = 0
)

const (
	PW_CLIENT_METHOD_ADD_LISTENER = iota
	PW_CLIENT_METHOD_ERROR
	PW_CLIENT_METHOD_UPDATE_PROPERTIES
	PW_CLIENT_METHOD_GET_PERMISSIONS
	PW_CLIENT_METHOD_UPDATE_PERMISSIONS
	PW_CLIENT_METHOD_NUM

	PW_VERSION_CLIENT_METHODS = 0
)

// The ClientInfo event provides client information updates.
// This is emitted when binding to a client or when the client info is updated later.
type ClientInfo struct {
	// The global id of the client.
	ID Int `json:"id"`
	// The changes emitted by this event.
	ChangeMask Long `json:"change_mask"`
	// Properties of this object, valid when change_mask has PW_CLIENT_CHANGE_MASK_PROPS.
	Properties *SPADict `json:"props"`
}

// Opcode satisfies [Message] with a constant value.
func (c *ClientInfo) Opcode() byte { return PW_CLIENT_EVENT_INFO }

// FileCount satisfies [Message] with a constant value.
func (c *ClientInfo) FileCount() Int { return 0 }

// Size satisfies [KnownSize] with a value computed at runtime.
func (c *ClientInfo) Size() Word {
	return SizePrefix +
		Size(SizeInt) +
		Size(SizeLong) +
		c.Properties.Size()
}

// MarshalBinary satisfies [encoding.BinaryMarshaler] via [Marshal].
func (c *ClientInfo) MarshalBinary() ([]byte, error) { return Marshal(c) }

// UnmarshalBinary satisfies [encoding.BinaryUnmarshaler] via [Unmarshal].
func (c *ClientInfo) UnmarshalBinary(data []byte) error { return Unmarshal(data, c) }

// ClientUpdateProperties is used to update the properties of a client.
type ClientUpdateProperties struct {
	// Properties to update on the client.
	Properties *SPADict `json:"props"`
}

// Opcode satisfies [Message] with a constant value.
func (c *ClientUpdateProperties) Opcode() byte { return PW_CLIENT_METHOD_UPDATE_PROPERTIES }

// FileCount satisfies [Message] with a constant value.
func (c *ClientUpdateProperties) FileCount() Int { return 0 }

// Size satisfies [KnownSize] with a value computed at runtime.
func (c *ClientUpdateProperties) Size() Word { return SizePrefix + c.Properties.Size() }

// MarshalBinary satisfies [encoding.BinaryMarshaler] via [Marshal].
func (c *ClientUpdateProperties) MarshalBinary() ([]byte, error) { return Marshal(c) }

// UnmarshalBinary satisfies [encoding.BinaryUnmarshaler] via [Unmarshal].
func (c *ClientUpdateProperties) UnmarshalBinary(data []byte) error { return Unmarshal(data, c) }

// clientUpdateProperties queues a [ClientUpdateProperties] message for the PipeWire server.
// This method should not be called directly, the New function queues this message.
func (ctx *Context) clientUpdateProperties(props SPADict) error {
	return ctx.writeMessage(
		PW_ID_CLIENT,
		&ClientUpdateProperties{&props},
	)
}

// Client holds state of [PW_TYPE_INTERFACE_Client].
type Client struct {
	// Additional information from the server, populated or updated during [Context.Roundtrip].
	Info *ClientInfo `json:"info"`

	// Populated by [CoreBoundProps] events targeting [Client].
	Properties SPADict `json:"props"`

	noRemove
}

func (client *Client) consume(opcode byte, files []int, unmarshal func(v any)) error {
	closeReceivedFiles(files...)
	switch opcode {
	case PW_CLIENT_EVENT_INFO:
		unmarshal(&client.Info)
		return nil

	default:
		panic(&UnsupportedOpcodeError{opcode, client.String()})
	}
}

func (client *Client) setBoundProps(event *CoreBoundProps) error {
	if event.Properties != nil {
		client.Properties = *event.Properties
	}
	return nil
}

func (client *Client) String() string { return PW_TYPE_INTERFACE_Registry }