4 /** Makes a bit mask from a channel position. \since 0.9.16 */
5 #define PA_CHANNEL_POSITION_MASK(f) ((pa_channel_position_mask_t) (1ULL << (f)))
8 #define PA_CHANNEL_POSITION_MASK_LEFT \
9 (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_LEFT) \
10 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_REAR_LEFT) \
11 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER) \
12 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_SIDE_LEFT) \
13 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_LEFT) \
14 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_LEFT)) \
16 #define PA_CHANNEL_POSITION_MASK_RIGHT \
17 (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_RIGHT) \
18 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_REAR_RIGHT) \
19 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER) \
20 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_SIDE_RIGHT) \
21 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_RIGHT) \
22 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_RIGHT))
24 #define PA_CHANNEL_POSITION_MASK_CENTER \
25 (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_CENTER) \
26 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_REAR_CENTER) \
27 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_CENTER) \
28 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_CENTER) \
29 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_CENTER))
31 #define PA_CHANNEL_POSITION_MASK_FRONT \
32 (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_LEFT) \
33 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_RIGHT) \
34 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_CENTER) \
35 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER) \
36 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER) \
37 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_LEFT) \
38 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_RIGHT) \
39 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_CENTER))
41 #define PA_CHANNEL_POSITION_MASK_REAR \
42 (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_REAR_LEFT) \
43 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_REAR_RIGHT) \
44 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_REAR_CENTER) \
45 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_LEFT) \
46 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_RIGHT) \
47 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_CENTER))
49 #define PA_CHANNEL_POSITION_MASK_SIDE_OR_TOP_CENTER \
50 (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_SIDE_LEFT) \
51 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_SIDE_RIGHT) \
52 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_CENTER))
54 #define PA_CHANNEL_POSITION_MASK_TOP \
55 (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_CENTER) \
56 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_LEFT) \
57 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_RIGHT) \
58 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_FRONT_CENTER) \
59 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_LEFT) \
60 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_RIGHT) \
61 | PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_TOP_REAR_CENTER))
63 #define PA_CHANNEL_POSITION_MASK_ALL \
64 ((pa_channel_position_mask_t) (PA_CHANNEL_POSITION_MASK(PA_CHANNEL_POSITION_MAX)-1))
66 const char *const channel_name_table[PA_CHANNEL_POSITION_MAX] = {
67 [PA_CHANNEL_POSITION_MONO] = _("Mono"),
69 [PA_CHANNEL_POSITION_FRONT_CENTER] = _("Front Center"),
70 [PA_CHANNEL_POSITION_FRONT_LEFT] = _("Front Left"),
71 [PA_CHANNEL_POSITION_FRONT_RIGHT] = _("Front Right"),
73 [PA_CHANNEL_POSITION_REAR_CENTER] = _("Rear Center"),
74 [PA_CHANNEL_POSITION_REAR_LEFT] = _("Rear Left"),
75 [PA_CHANNEL_POSITION_REAR_RIGHT] = _("Rear Right"),
77 [PA_CHANNEL_POSITION_LFE] = _("Subwoofer"),
79 [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = _("Front Left-of-center"),
80 [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = _("Front Right-of-center"),
82 [PA_CHANNEL_POSITION_SIDE_LEFT] = _("Side Left"),
83 [PA_CHANNEL_POSITION_SIDE_RIGHT] = _("Side Right"),
85 [PA_CHANNEL_POSITION_AUX0] = _("Auxiliary 0"),
86 [PA_CHANNEL_POSITION_AUX1] = _("Auxiliary 1"),
87 [PA_CHANNEL_POSITION_AUX2] = _("Auxiliary 2"),
88 [PA_CHANNEL_POSITION_AUX3] = _("Auxiliary 3"),
89 [PA_CHANNEL_POSITION_AUX4] = _("Auxiliary 4"),
90 [PA_CHANNEL_POSITION_AUX5] = _("Auxiliary 5"),
91 [PA_CHANNEL_POSITION_AUX6] = _("Auxiliary 6"),
92 [PA_CHANNEL_POSITION_AUX7] = _("Auxiliary 7"),
93 [PA_CHANNEL_POSITION_AUX8] = _("Auxiliary 8"),
94 [PA_CHANNEL_POSITION_AUX9] = _("Auxiliary 9"),
95 [PA_CHANNEL_POSITION_AUX10] = _("Auxiliary 10"),
96 [PA_CHANNEL_POSITION_AUX11] = _("Auxiliary 11"),
97 [PA_CHANNEL_POSITION_AUX12] = _("Auxiliary 12"),
98 [PA_CHANNEL_POSITION_AUX13] = _("Auxiliary 13"),
99 [PA_CHANNEL_POSITION_AUX14] = _("Auxiliary 14"),
100 [PA_CHANNEL_POSITION_AUX15] = _("Auxiliary 15"),
101 [PA_CHANNEL_POSITION_AUX16] = _("Auxiliary 16"),
102 [PA_CHANNEL_POSITION_AUX17] = _("Auxiliary 17"),
103 [PA_CHANNEL_POSITION_AUX18] = _("Auxiliary 18"),
104 [PA_CHANNEL_POSITION_AUX19] = _("Auxiliary 19"),
105 [PA_CHANNEL_POSITION_AUX20] = _("Auxiliary 20"),
106 [PA_CHANNEL_POSITION_AUX21] = _("Auxiliary 21"),
107 [PA_CHANNEL_POSITION_AUX22] = _("Auxiliary 22"),
108 [PA_CHANNEL_POSITION_AUX23] = _("Auxiliary 23"),
109 [PA_CHANNEL_POSITION_AUX24] = _("Auxiliary 24"),
110 [PA_CHANNEL_POSITION_AUX25] = _("Auxiliary 25"),
111 [PA_CHANNEL_POSITION_AUX26] = _("Auxiliary 26"),
112 [PA_CHANNEL_POSITION_AUX27] = _("Auxiliary 27"),
113 [PA_CHANNEL_POSITION_AUX28] = _("Auxiliary 28"),
114 [PA_CHANNEL_POSITION_AUX29] = _("Auxiliary 29"),
115 [PA_CHANNEL_POSITION_AUX30] = _("Auxiliary 30"),
116 [PA_CHANNEL_POSITION_AUX31] = _("Auxiliary 31"),
118 [PA_CHANNEL_POSITION_TOP_CENTER] = _("Top Center"),
120 [PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = _("Top Front Center"),
121 [PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = _("Top Front Left"),
122 [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = _("Top Front Right"),
124 [PA_CHANNEL_POSITION_TOP_REAR_CENTER] = _("Top Rear Center"),
125 [PA_CHANNEL_POSITION_TOP_REAR_LEFT] = _("Top Rear Left"),
126 [PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = _("Top Rear Right")
129 static Eina_Bool on_left(pa_channel_position_t p) {
130 return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_LEFT);
133 static Eina_Bool on_right(pa_channel_position_t p) {
134 return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_RIGHT);
137 static Eina_Bool on_center(pa_channel_position_t p) {
138 return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_CENTER);
141 static Eina_Bool on_lfe(pa_channel_position_t p) {
142 return p == PA_CHANNEL_POSITION_LFE;
145 static Eina_Bool on_front(pa_channel_position_t p) {
146 return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_FRONT);
149 static Eina_Bool on_rear(pa_channel_position_t p) {
150 return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_REAR);
154 pulse_sink_port_info_free(Pulse_Sink_Port_Info *pi)
157 eina_stringshare_del(pi->name);
158 eina_stringshare_del(pi->description);
163 pulse_sink_free(Pulse_Sink *sink)
165 Pulse_Sink_Port_Info *pi;
169 sink->deleted = EINA_TRUE;
172 eina_hash_del_by_key(pulse_sources, (uintptr_t*)&sink->index);
177 eina_hash_del_by_key(pulse_sinks, (uintptr_t*)&sink->index);
181 eina_stringshare_del(sink->name);
182 eina_stringshare_del(sink->description);
183 EINA_LIST_FREE(sink->ports, pi)
184 pulse_sink_port_info_free(pi);
185 eina_stringshare_del(sink->active_port);
190 pulse_sink_ports_get(Pulse_Sink *sink)
192 EINA_SAFETY_ON_NULL_RETURN_VAL(sink, NULL);
197 pulse_sink_port_active_get(Pulse_Sink *sink)
199 EINA_SAFETY_ON_NULL_RETURN_VAL(sink, NULL);
200 return sink->active_port;
204 pulse_sink_name_get(Pulse_Sink *sink)
206 EINA_SAFETY_ON_NULL_RETURN_VAL(sink, NULL);
212 pulse_sink_desc_get(Pulse_Sink *sink)
214 EINA_SAFETY_ON_NULL_RETURN_VAL(sink, NULL);
216 return sink->description;
220 pulse_sink_idx_get(Pulse_Sink *sink)
222 EINA_SAFETY_ON_NULL_RETURN_VAL(sink, 0);
228 pulse_sink_muted_get(Pulse_Sink *sink)
230 EINA_SAFETY_ON_NULL_RETURN_VAL(sink, EINA_FALSE);
236 pulse_sink_channels_count(Pulse_Sink *sink)
238 EINA_SAFETY_ON_NULL_RETURN_VAL(sink, 0);
240 return sink->volume.channels;
244 pulse_sink_avg_get_pct(Pulse_Sink *sink)
249 EINA_SAFETY_ON_NULL_RETURN_VAL(sink, -1.0);
251 for (avg = 0, x = 0; x < sink->volume.channels; x++)
252 avg += sink->volume.values[x];
253 avg /= sink->volume.channels;
255 if (avg <= PA_VOLUME_MUTED) return 0.0;
257 if (avg == PA_VOLUME_NORM) return 100.0;
259 return (avg * 100 + PA_VOLUME_NORM / 2) / PA_VOLUME_NORM;
263 pulse_sink_channel_names_get(Pulse_Sink *sink)
265 Eina_List *ret = NULL;
268 EINA_SAFETY_ON_NULL_RETURN_VAL(sink, NULL);
269 for (x = 0; x < sink->volume.channels; x++)
270 ret = eina_list_append(ret, pulse_sink_channel_id_get_name(sink, x));
275 pulse_sink_channel_name_get_id(Pulse_Sink *sink, const char *name)
279 EINA_SAFETY_ON_NULL_RETURN_VAL(sink, UINT_MAX);
280 EINA_SAFETY_ON_NULL_RETURN_VAL(name, UINT_MAX);
281 for (x = 0; x < sink->channel_map.channels; x++)
283 if (!strcmp(name, channel_name_table[sink->channel_map.map[x]]))
290 pulse_sink_channel_id_get_name(Pulse_Sink *sink, unsigned int id)
292 EINA_SAFETY_ON_NULL_RETURN_VAL(sink, NULL);
293 EINA_SAFETY_ON_TRUE_RETURN_VAL(id >= sink->channel_map.channels, NULL);
294 return eina_stringshare_add(channel_name_table[sink->channel_map.map[id]]);
298 pulse_sink_channel_volume_get(Pulse_Sink *sink, unsigned int id)
300 EINA_SAFETY_ON_NULL_RETURN_VAL(sink, -1);
301 EINA_SAFETY_ON_TRUE_RETURN_VAL(id >= sink->channel_map.channels, -1);
302 return (sink->volume.values[id] * 100 + PA_VOLUME_NORM / 2) / PA_VOLUME_NORM;
306 pulse_sink_channel_balance_get(Pulse_Sink *sink, unsigned int id)
308 EINA_SAFETY_ON_NULL_RETURN_VAL(sink, -1.0);
309 EINA_SAFETY_ON_TRUE_RETURN_VAL(id >= sink->channel_map.channels, -1.0);
311 if (on_left(sink->channel_map.map[id])) return 0.0;
312 if (on_right(sink->channel_map.map[id])) return 1.0;
317 pulse_sink_channel_depth_get(Pulse_Sink *sink, unsigned int id)
319 EINA_SAFETY_ON_NULL_RETURN_VAL(sink, -1.0);
320 EINA_SAFETY_ON_TRUE_RETURN_VAL(id >= sink->channel_map.channels, -1.0);
322 if (on_rear(sink->channel_map.map[id])) return 0.0;
323 if (on_front(sink->channel_map.map[id])) return 1.0;
328 pulse_sink_balance_get(Pulse_Sink *sink)
332 pa_volume_t left = 0, right = 0;
333 unsigned n_left = 0, n_right = 0;
335 for (c = 0; c < sink->channel_map.channels; c++) {
336 if (on_left(sink->channel_map.map[c])) {
337 left += sink->volume.values[c];
339 } else if (on_right(sink->channel_map.map[c])) {
340 right += sink->volume.values[c];
354 l /= (float)PA_VOLUME_NORM;
355 r /= (float)PA_VOLUME_NORM;