1 /* PipeWire
2  *
3  * Copyright © 2020 Wim Taymans
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 
25 #ifndef PULSE_SERVER_DEFS_H
26 #define PULSE_SERVER_DEFS_H
27 
28 #include <pipewire/node.h>
29 
30 #define FLAG_SHMDATA			0x80000000LU
31 #define FLAG_SHMDATA_MEMFD_BLOCK	0x20000000LU
32 #define FLAG_SHMRELEASE			0x40000000LU
33 #define FLAG_SHMREVOKE			0xC0000000LU
34 #define FLAG_SHMMASK			0xFF000000LU
35 #define FLAG_SEEKMASK			0x000000FFLU
36 #define FLAG_SHMWRITABLE		0x00800000LU
37 
38 #define SEEK_RELATIVE		0
39 #define SEEK_ABSOLUTE		1
40 #define SEEK_RELATIVE_ON_READ	2
41 #define SEEK_RELATIVE_END	3
42 
43 #define FRAME_SIZE_MAX_ALLOW (1024*1024*16)
44 
45 #define PROTOCOL_FLAG_MASK	0xffff0000u
46 #define PROTOCOL_VERSION_MASK	0x0000ffffu
47 #define PROTOCOL_VERSION	35
48 
49 #define NATIVE_COOKIE_LENGTH 256
50 #define MAX_TAG_SIZE (64*1024)
51 
52 #define MIN_BUFFERS     1u
53 #define MAX_BUFFERS     4u
54 
55 #define MAXLENGTH		(4*1024*1024) /* 4MB */
56 
57 #define SCACHE_ENTRY_SIZE_MAX	(1024*1024*16)
58 
59 #define INDEX_MASK		0xffffu
60 #define MONITOR_FLAG		(1u << 16)
61 #define EXTENSION_FLAG		(1u << 17)
62 #define MODULE_FLAG		(1u << 18)
63 
64 #define DEFAULT_SINK		"@DEFAULT_SINK@"
65 #define DEFAULT_SOURCE		"@DEFAULT_SOURCE@"
66 #define DEFAULT_MONITOR		"@DEFAULT_MONITOR@"
67 
68 enum error_code {
69 	ERR_OK = 0,			/**< No error */
70 	ERR_ACCESS,			/**< Access failure */
71 	ERR_COMMAND,			/**< Unknown command */
72 	ERR_INVALID,			/**< Invalid argument */
73 	ERR_EXIST,			/**< Entity exists */
74 	ERR_NOENTITY,			/**< No such entity */
75 	ERR_CONNECTIONREFUSED,		/**< Connection refused */
76 	ERR_PROTOCOL,			/**< Protocol error */
77 	ERR_TIMEOUT,			/**< Timeout */
78 	ERR_AUTHKEY,			/**< No authentication key */
79 	ERR_INTERNAL,			/**< Internal error */
80 	ERR_CONNECTIONTERMINATED,	/**< Connection terminated */
81 	ERR_KILLED,			/**< Entity killed */
82 	ERR_INVALIDSERVER,		/**< Invalid server */
83 	ERR_MODINITFAILED,		/**< Module initialization failed */
84 	ERR_BADSTATE,			/**< Bad state */
85 	ERR_NODATA,			/**< No data */
86 	ERR_VERSION,			/**< Incompatible protocol version */
87 	ERR_TOOLARGE,			/**< Data too large */
88 	ERR_NOTSUPPORTED,		/**< Operation not supported \since 0.9.5 */
89 	ERR_UNKNOWN,			/**< The error code was unknown to the client */
90 	ERR_NOEXTENSION,		/**< Extension does not exist. \since 0.9.12 */
91 	ERR_OBSOLETE,			/**< Obsolete functionality. \since 0.9.15 */
92 	ERR_NOTIMPLEMENTED,		/**< Missing implementation. \since 0.9.15 */
93 	ERR_FORKED,			/**< The caller forked without calling execve() and tried to reuse the context. \since 0.9.15 */
94 	ERR_IO,				/**< An IO error happened. \since 0.9.16 */
95 	ERR_BUSY,			/**< Device or resource busy. \since 0.9.17 */
96 	ERR_MAX				/**< Not really an error but the first invalid error code */
97 };
98 
res_to_err(int res)99 static inline int res_to_err(int res)
100 {
101 	switch (res) {
102 	case 0: return ERR_OK;
103 	case -EACCES: case -EPERM: return ERR_ACCESS;
104 	case -ENOTTY: return ERR_COMMAND;
105 	case -EINVAL: return ERR_INVALID;
106 	case -EEXIST: return ERR_EXIST;
107 	case -ENOENT: case -ESRCH: case -ENXIO: case -ENODEV: return ERR_NOENTITY;
108 	case -ECONNREFUSED:
109 #ifdef ENONET
110 	case -ENONET:
111 #endif
112 	case -EHOSTDOWN: case -ENETDOWN: return ERR_CONNECTIONREFUSED;
113 	case -EPROTO: case -EBADMSG: return ERR_PROTOCOL;
114 	case -ETIMEDOUT:
115 #ifdef ETIME
116 	case -ETIME:
117 #endif
118 		return ERR_TIMEOUT;
119 #ifdef ENOKEY
120 	case -ENOKEY: return ERR_AUTHKEY;
121 #endif
122 	case -ECONNRESET: case -EPIPE: return ERR_CONNECTIONTERMINATED;
123 #ifdef EBADFD
124 	case -EBADFD: return ERR_BADSTATE;
125 #endif
126 #ifdef ENODATA
127 	case -ENODATA: return ERR_NODATA;
128 #endif
129 	case -EOVERFLOW: case -E2BIG: case -EFBIG:
130 	case -ERANGE: case -ENAMETOOLONG: return ERR_TOOLARGE;
131 	case -ENOTSUP: case -EPROTONOSUPPORT: case -ESOCKTNOSUPPORT: return ERR_NOTSUPPORTED;
132 	case -ENOSYS: return ERR_NOTIMPLEMENTED;
133 	case -EIO: return ERR_IO;
134 	case -EBUSY: return ERR_BUSY;
135 	case -ENFILE: case -EMFILE: return ERR_INTERNAL;
136 	}
137 	return ERR_UNKNOWN;
138 }
139 
140 enum {
141 	SUBSCRIPTION_MASK_NULL = 0x0000U,
142 	SUBSCRIPTION_MASK_SINK = 0x0001U,
143 	SUBSCRIPTION_MASK_SOURCE = 0x0002U,
144 	SUBSCRIPTION_MASK_SINK_INPUT = 0x0004U,
145 	SUBSCRIPTION_MASK_SOURCE_OUTPUT = 0x0008U,
146 	SUBSCRIPTION_MASK_MODULE = 0x0010U,
147 	SUBSCRIPTION_MASK_CLIENT = 0x0020U,
148 	SUBSCRIPTION_MASK_SAMPLE_CACHE = 0x0040U,
149 	SUBSCRIPTION_MASK_SERVER = 0x0080U,
150 	SUBSCRIPTION_MASK_AUTOLOAD = 0x0100U,
151 	SUBSCRIPTION_MASK_CARD = 0x0200U,
152 	SUBSCRIPTION_MASK_ALL = 0x02ffU
153 };
154 
155 enum {
156 	SUBSCRIPTION_EVENT_SINK = 0x0000U,
157 	SUBSCRIPTION_EVENT_SOURCE = 0x0001U,
158 	SUBSCRIPTION_EVENT_SINK_INPUT = 0x0002U,
159 	SUBSCRIPTION_EVENT_SOURCE_OUTPUT = 0x0003U,
160 	SUBSCRIPTION_EVENT_MODULE = 0x0004U,
161 	SUBSCRIPTION_EVENT_CLIENT = 0x0005U,
162 	SUBSCRIPTION_EVENT_SAMPLE_CACHE = 0x0006U,
163 	SUBSCRIPTION_EVENT_SERVER = 0x0007U,
164 	SUBSCRIPTION_EVENT_AUTOLOAD = 0x0008U,
165 	SUBSCRIPTION_EVENT_CARD = 0x0009U,
166 	SUBSCRIPTION_EVENT_FACILITY_MASK = 0x000FU,
167 
168 	SUBSCRIPTION_EVENT_NEW = 0x0000U,
169 	SUBSCRIPTION_EVENT_CHANGE = 0x0010U,
170 	SUBSCRIPTION_EVENT_REMOVE = 0x0020U,
171 	SUBSCRIPTION_EVENT_TYPE_MASK = 0x0030U
172 };
173 
174 enum {
175 	STATE_INVALID = -1,
176 	STATE_RUNNING = 0,
177 	STATE_IDLE = 1,
178 	STATE_SUSPENDED = 2,
179 	STATE_INIT = -2,
180 	STATE_UNLINKED = -3
181 };
182 
node_state(enum pw_node_state state)183 static inline int node_state(enum pw_node_state state)
184 {
185 	switch (state) {
186 	case PW_NODE_STATE_ERROR:
187 		return STATE_UNLINKED;
188 	case PW_NODE_STATE_CREATING:
189 		return STATE_INIT;
190 	case PW_NODE_STATE_SUSPENDED:
191 		return STATE_SUSPENDED;
192 	case PW_NODE_STATE_IDLE:
193 		return STATE_IDLE;
194 	case PW_NODE_STATE_RUNNING:
195 		return STATE_RUNNING;
196 	}
197 	return STATE_INVALID;
198 }
199 
200 enum {
201 	SINK_HW_VOLUME_CTRL = 0x0001U,
202 	SINK_LATENCY = 0x0002U,
203 	SINK_HARDWARE = 0x0004U,
204 	SINK_NETWORK = 0x0008U,
205 	SINK_HW_MUTE_CTRL = 0x0010U,
206 	SINK_DECIBEL_VOLUME = 0x0020U,
207 	SINK_FLAT_VOLUME = 0x0040U,
208 	SINK_DYNAMIC_LATENCY = 0x0080U,
209 	SINK_SET_FORMATS = 0x0100U,
210 };
211 
212 enum {
213 	SOURCE_HW_VOLUME_CTRL = 0x0001U,
214 	SOURCE_LATENCY = 0x0002U,
215 	SOURCE_HARDWARE = 0x0004U,
216 	SOURCE_NETWORK = 0x0008U,
217 	SOURCE_HW_MUTE_CTRL = 0x0010U,
218 	SOURCE_DECIBEL_VOLUME = 0x0020U,
219 	SOURCE_DYNAMIC_LATENCY = 0x0040U,
220 	SOURCE_FLAT_VOLUME = 0x0080U,
221 };
222 
223 static const char * const port_types[] = {
224 	"unknown",
225 	"aux",
226 	"speaker",
227 	"headphones",
228 	"line",
229 	"mic",
230 	"headset",
231 	"handset",
232 	"earpiece",
233 	"spdif",
234 	"hdmi",
235 	"tv",
236 	"radio",
237 	"video",
238 	"usb",
239 	"bluetooth",
240 	"portable",
241 	"handsfree",
242 	"car",
243 	"hifi",
244 	"phone",
245 	"network",
246 	"analog",
247 };
248 
port_type_value(const char * port_type)249 static inline uint32_t port_type_value(const char *port_type)
250 {
251 	uint32_t i;
252 	for (i = 0; i < SPA_N_ELEMENTS(port_types); i++) {
253 		if (strcmp(port_types[i], port_type) == 0)
254 			return i;
255 	}
256 	return 0;
257 }
258 
259 #define METADATA_DEFAULT_SINK           "default.audio.sink"
260 #define METADATA_DEFAULT_SOURCE         "default.audio.source"
261 #define METADATA_CONFIG_DEFAULT_SINK    "default.configured.audio.sink"
262 #define METADATA_CONFIG_DEFAULT_SOURCE  "default.configured.audio.source"
263 #define METADATA_TARGET_NODE            "target.node"
264 
265 #endif /* PULSE_SERVER_DEFS_H */
266