4 tag_uint32(Pulse_Tag *tag, uint32_t val)
8 ret = tag->data + tag->size;
11 memcpy(ret + 1, &val, sizeof(val));
12 ret += PA_TAG_SIZE_U32;
13 tag->size = ret - tag->data;
18 untag_uint32(Pulse_Tag *tag, uint32_t *val)
22 ret = tag->data + tag->size;
23 if ((*ret != PA_TAG_U32) && (*ret != PA_TAG_VOLUME)) return 0;
24 memcpy(val, ret + 1, sizeof(uint32_t));
26 ret += PA_TAG_SIZE_U32;
27 tag->size = ret - tag->data;
32 tag_bool(Pulse_Tag *tag, Eina_Bool val)
36 ret = tag->data + tag->size;
37 *ret = (uint8_t)(val ? PA_TAG_BOOLEAN_TRUE : PA_TAG_BOOLEAN_FALSE);
38 ret += PA_TAG_SIZE_BOOLEAN;
39 tag->size = ret - tag->data;
44 untag_bool(Pulse_Tag *tag, Eina_Bool *val)
48 ret = tag->data + tag->size;
49 if ((*ret != PA_TAG_BOOLEAN_TRUE) && (*ret != PA_TAG_BOOLEAN_FALSE)) return 0;
50 *val = !!(*ret == PA_TAG_BOOLEAN_TRUE) ? EINA_TRUE : EINA_FALSE;
51 ret += PA_TAG_SIZE_BOOLEAN;
52 tag->size = ret - tag->data;
57 tag_string(Pulse_Tag *tag, const char *val)
61 ret = tag->data + tag->size;
65 strcpy((char*)ret + 1, val);
66 ret += PA_TAG_SIZE_STRING + strlen(val);
67 tag->size = ret - tag->data;
70 *ret = PA_TAG_STRING_NULL, tag->size++;
75 untag_string(Pulse_Tag *tag, const char **val)
79 ret = tag->data + tag->size;
83 eina_stringshare_replace(val, (char*)ret + 1);
84 ret += PA_TAG_SIZE_STRING + strlen(*val);
86 case PA_TAG_STRING_NULL:
88 ret += PA_TAG_SIZE_STRING_NULL;
93 tag->size = ret - tag->data;
98 untag_sample(Pulse_Tag *tag, pa_sample_spec *spec)
102 ret = tag->data + tag->size;
103 if (*ret != PA_TAG_SAMPLE_SPEC) return 0;
105 spec->format = ret[1];
106 spec->channels = ret[2];
107 memcpy(&spec->rate, ret + 3, sizeof(spec->rate));
108 spec->rate = ntohl(spec->rate);
109 ret += PA_TAG_SIZE_SAMPLE_SPEC, tag->size += PA_TAG_SIZE_SAMPLE_SPEC;
114 untag_channel_map(Pulse_Tag *tag, pa_channel_map *map)
119 ret = tag->data + tag->size;
120 if (*ret != PA_TAG_CHANNEL_MAP) return 0;
122 map->channels = ret[1];
123 if (map->channels > PA_CHANNELS_MAX) return 0;
124 if (map->channels + 2 + tag->size > tag->dsize) return 0;
126 for (ret += 2, x = 0; x < map->channels; ret++, x++)
127 map->map[x] = (int8_t)*ret;
129 tag->size = ret - tag->data;
134 untag_usec(Pulse_Tag *tag, uint64_t *val)
139 ret = tag->data + tag->size;
140 if (*ret != PA_TAG_USEC) return 0;
142 memcpy(&tmp, ret + 1, 4);
143 *val = (uint64_t)ntohl(tmp) << 32;
144 memcpy(&tmp, ret + 5, 4);
145 *val |= (uint64_t)ntohl(tmp);
146 ret += PA_TAG_SIZE_USEC;
147 tag->size = ret - tag->data;
152 tag_arbitrary(Pulse_Tag *tag, const void *val, uint32_t size)
157 ret = tag->data + tag->size;
158 *ret = PA_TAG_ARBITRARY;
160 memcpy(ret + 1, &tmp, sizeof(uint32_t));
161 memcpy(ret + PA_TAG_SIZE_U32, val, size);
162 ret += PA_TAG_SIZE_ARBITRARY + size;
163 tag->size = ret - tag->data;
168 untag_arbitrary(Pulse_Tag *tag, Eina_Binbuf **val)
173 if (!untag_uint32(tag, &len)) return 0;
174 ret = tag->data + tag->size;
175 if (*ret != PA_TAG_ARBITRARY) return 0;
176 ret += PA_TAG_SIZE_ARBITRARY;
178 *val = eina_binbuf_new();
179 eina_binbuf_append_length(*val, ret, len);
181 tag->size = ret - tag->data;
186 tag_simple_init(Pulse *conn, Pulse_Tag *tag, uint32_t val, PA_Tag type)
191 tag_uint32(tag, val);
192 return tag_uint32(tag, conn->tag_count++);
200 tag_proplist_foreach(const Eina_Hash *h __UNUSED__, const char *key, const char *val, Pulse_Tag *tag)
204 tag_string(tag, key);
205 size = strlen(val) + 1;
206 tag_uint32(tag, size);
207 tag_arbitrary(tag, val, size);
212 tag_proplist(Pulse_Tag *tag)
216 ret = tag->data + tag->size;
217 *ret = PA_TAG_PROPLIST, tag->size++;
219 eina_hash_foreach(tag->props, (Eina_Hash_Foreach)tag_proplist_foreach, tag);
220 return tag_string(tag, NULL);
224 untag_proplist(Pulse_Tag *tag, Eina_Hash **props)
228 ret = tag->data + tag->size;
229 if (*ret != PA_TAG_PROPLIST) return 0;
231 *props = eina_hash_string_superfast_new((Eina_Free_Cb)eina_binbuf_free);
232 for (++tag->size; *ret != PA_TAG_STRING_NULL && tag->size < tag->dsize - 1;)
234 const char *key = NULL;
236 EINA_SAFETY_ON_FALSE_GOTO(untag_string(tag, &key), error);
237 EINA_SAFETY_ON_FALSE_GOTO(untag_arbitrary(tag, &val), error);
241 snprintf(buf, sizeof(buf), "key='%%s', val='%%.%zus'", eina_binbuf_length_get(val));
242 DBG(buf, key, eina_binbuf_string_get(val));
245 eina_hash_add(*props, key, val);
246 eina_stringshare_del(key);
247 ret = tag->data + tag->size;
252 eina_hash_free(*props);
257 tag_volume(Pulse_Tag *tag, uint8_t channels, double vol)
262 if (vol <= 0.0) pa_vol = PA_VOLUME_MUTED;
263 else pa_vol = ((vol * PA_VOLUME_NORM) - (PA_VOLUME_NORM / 2)) / 100;
264 pa_vol = htonl(pa_vol);
265 ret = tag->data + tag->size;
266 *ret++ = PA_TAG_CVOLUME;
268 for (x = 0; x < channels; x++, ret += sizeof(pa_vol))
269 memcpy(ret, &pa_vol, sizeof(pa_vol));
270 tag->size = ret - tag->data;
275 tag_cvol(Pulse_Tag *tag, pa_cvolume *c)
280 ret = tag->data + tag->size;
281 *ret++ = PA_TAG_CVOLUME;
282 *ret++ = c->channels;
283 for (x = 0; x < c->channels; x++, ret += sizeof(pa_vol))
285 pa_vol = htonl(c->values[x]);
286 memcpy(ret, &pa_vol, sizeof(pa_vol));
288 tag->size = ret - tag->data;
293 untag_cvol(Pulse_Tag *tag, pa_cvolume *cvol)
298 ret = tag->data + tag->size;
299 if (*ret != PA_TAG_CVOLUME) return 0;
300 cvol->channels = ret[1];
301 for (x = 0, ret += 2; x < cvol->channels; x++, ret += sizeof(pa_vol))
303 memcpy(&pa_vol, ret, sizeof(pa_vol));
304 cvol->values[x] = ntohl(pa_vol);
307 tag->size = ret - tag->data;
312 tag_finish(Pulse_Tag *tag)
314 EINA_SAFETY_ON_NULL_RETURN(tag);
315 tag->header[PA_PSTREAM_DESCRIPTOR_CHANNEL] = htonl((uint32_t) -1);
316 tag->header[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(tag->dsize);
320 pulse_tag_free(Pulse_Tag *tag)
324 if (tag->props) eina_hash_free(tag->props);