/* The following is based on an example from the GNU libc documentation */ size_t pa_strbuf_printf(pa_strbuf *sb, const char *format, ...) { size_t size = 100; struct chunk *c = NULL; pa_assert(sb); pa_assert(format); for(;;) { va_list ap; int r; c = pa_xrealloc(c, PA_ALIGN(sizeof(struct chunk)) + size); va_start(ap, format); r = vsnprintf(CHUNK_TO_TEXT(c), size, format, ap); CHUNK_TO_TEXT(c)[size-1] = 0; va_end(ap); if (r > -1 && (size_t) r < size) { c->length = (size_t) r; append(sb, c); return (size_t) r; } if (r > -1) /* glibc 2.1 */ size = (size_t) r+1; else /* glibc 2.0 */ size *= 2; } }
/* Same as the previous function, but use a va_list instead of an * ellipsis */ char *pa_vsprintf_malloc(const char *format, va_list ap) { int size = 100; char *c = NULL; pa_assert(format); for(;;) { int r; va_list aq; c = pa_xrealloc(c, size); va_copy(aq, ap); r = vsnprintf(c, size, format, aq); va_end(aq); c[size-1] = 0; if (r > -1 && r < size) return c; if (r > -1) /* glibc 2.1 */ size = r+1; else /* glibc 2.0 */ size *= 2; } }
static inline void extend(pa_tagstruct*t, size_t l) { pa_assert(t); pa_assert(t->type != PA_TAGSTRUCT_FIXED); if (t->length+l <= t->allocated) return; t->data = pa_xrealloc(t->data, t->allocated = t->length+l+100); }
void pa_dynarray_append(pa_dynarray *array, void *p) { pa_assert(array); pa_assert(p); if (array->n_entries == array->n_allocated) { unsigned n = PA_MAX(array->n_allocated * 2, 25U); array->data = pa_xrealloc(array->data, sizeof(void *) * n); array->n_allocated = n; } array->data[array->n_entries++] = p; }
static inline void extend(pa_tagstruct*t, size_t l) { pa_assert(t); pa_assert(t->type != PA_TAGSTRUCT_FIXED); if (t->length+l <= t->allocated) return; if (t->type == PA_TAGSTRUCT_DYNAMIC) t->data = pa_xrealloc(t->data, t->allocated = t->length + l + GROW_TAG_SIZE); else if (t->type == PA_TAGSTRUCT_APPENDED) { t->type = PA_TAGSTRUCT_DYNAMIC; t->data = pa_xmalloc(t->allocated = t->length + l + GROW_TAG_SIZE); memcpy(t->data, t->per_type.appended, t->length); } }
static char* iconv_simple(const char *str, const char *to, const char *from) { char *new_str; size_t len, inlen; iconv_t cd; ICONV_CONST char *inbuf; char *outbuf; size_t res, inbytes, outbytes; pa_assert(str); pa_assert(to); pa_assert(from); cd = iconv_open(to, from); if (cd == (iconv_t)-1) return NULL; inlen = len = strlen(str) + 1; new_str = pa_xmalloc(len); for (;;) { inbuf = (ICONV_CONST char*) str; /* Brain dead prototype for iconv() */ inbytes = inlen; outbuf = new_str; outbytes = len; res = iconv(cd, &inbuf, &inbytes, &outbuf, &outbytes); if (res != (size_t)-1) break; if (errno != E2BIG) { pa_xfree(new_str); new_str = NULL; break; } pa_assert(inbytes != 0); len += inbytes; new_str = pa_xrealloc(new_str, len); } iconv_close(cd); return new_str; }
/** * Pulseaudio callback when new data is available. */ static void stream_read_callback (pa_stream * s, size_t length, void *userdata) { const void *data; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got %u/%u bytes of PCM data\n", length, pcm_length); GNUNET_assert (NULL != s); GNUNET_assert (length > 0); if (stdio_event) mainloop_api->io_enable (stdio_event, PA_IO_EVENT_OUTPUT); if (pa_stream_peek (s, (const void **) &data, &length) < 0) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("pa_stream_peek() failed: %s\n"), pa_strerror (pa_context_errno (context))); quit (1); return; } GNUNET_assert (NULL != data); GNUNET_assert (length > 0); if (NULL != transmit_buffer) { transmit_buffer = pa_xrealloc (transmit_buffer, transmit_buffer_length + length); memcpy (&transmit_buffer[transmit_buffer_length], data, length); transmit_buffer_length += length; } else { transmit_buffer = pa_xmalloc (length); memcpy (transmit_buffer, data, length); transmit_buffer_length = length; transmit_buffer_index = 0; } pa_stream_drop (s); packetizer (); }
pa_prioq_item* pa_prioq_put(pa_prioq *q, void *p) { pa_prioq_item *i; pa_assert(q); if (q->n_items >= q->n_allocated) { q->n_allocated = PA_MAX(q->n_items+1, q->n_allocated)*2; q->items = pa_xrealloc(q->items, sizeof(pa_prioq_item*) * q->n_allocated); } if (!(i = pa_flist_pop(PA_STATIC_FLIST_GET(items)))) i = pa_xnew(pa_prioq_item, 1); i->value = p; i->idx = q->n_items++; shuffle_up(q, i); return i; }
static void devices_add(struct pa_classify_device **p_devices, const char *type, const char *prop, enum pa_classify_method method, const char *arg, pa_hashmap *ports, uint32_t flags) { struct pa_classify_device *devs; struct pa_classify_device_def *d; size_t newsize; const char *method_name; char *ports_string = NULL; /* Just for log output. */ pa_strbuf *buf; /* For building ports_string. */ pa_assert(p_devices); pa_assert_se((devs = *p_devices)); newsize = sizeof(*devs) + sizeof(devs->defs[0]) * (devs->ndef + 1); devs = *p_devices = pa_xrealloc(devs, newsize); d = devs->defs + devs->ndef; memset(d+1, 0, sizeof(devs->defs[0])); d->type = pa_xstrdup(type); d->prop = pa_xstrdup(prop); buf = pa_strbuf_new(); if (ports && !pa_hashmap_isempty(ports)) { struct pa_classify_port_entry *port; void *state; pa_bool_t first = TRUE; /* Copy the ports hashmap to d->data.ports. */ d->data.ports = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func); PA_HASHMAP_FOREACH(port, ports, state) { struct pa_classify_port_entry *port_copy = pa_xnew(struct pa_classify_port_entry, 1); port_copy->device_name = pa_xstrdup(port->device_name); port_copy->port_name = pa_xstrdup(port->port_name); pa_hashmap_put(d->data.ports, port_copy->device_name, port_copy); if (!first) { pa_strbuf_putc(buf, ','); } first = FALSE; pa_strbuf_printf(buf, "%s:%s", port->device_name, port->port_name); } } d->data.flags = flags; switch (method) { case pa_method_equals: method_name = "equals"; d->method = pa_classify_method_equals; d->arg.string = pa_xstrdup(arg); break; case pa_method_startswith: method_name = "startswidth"; d->method = pa_classify_method_startswith; d->arg.string = pa_xstrdup(arg); break; case pa_method_matches: method_name = "matches"; if (regcomp(&d->arg.rexp, arg, 0) == 0) { d->method = pa_classify_method_matches; break; } /* intentional fall trough */ default: pa_log("%s: invalid device definition %s", __FUNCTION__, type); memset(d, 0, sizeof(*d)); pa_strbuf_free(buf); return; } devs->ndef++; ports_string = pa_strbuf_tostring_free(buf); pa_log_info("device '%s' added (%s|%s|%s|%s|0x%04x)", type, d->prop, method_name, arg, ports_string, d->data.flags); pa_xfree(ports_string); }
static void cards_add(struct pa_classify_card **p_cards, char *type, enum pa_classify_method method[2], char **arg, char **profiles, uint32_t flags[2]) { struct pa_classify_card *cards; struct pa_classify_card_def *d; struct pa_classify_card_data *data; size_t newsize; char *method_name[2]; int i; pa_assert(p_cards); pa_assert_se((cards = *p_cards)); newsize = sizeof(*cards) + sizeof(cards->defs[0]) * (cards->ndef + 1); cards = *p_cards = pa_xrealloc(cards, newsize); d = cards->defs + cards->ndef; memset(d+1, 0, sizeof(cards->defs[0])); d->type = pa_xstrdup(type); for (i = 0; i < 2 && profiles[i]; i++) { data = &d->data[i]; data->profile = profiles[i] ? pa_xstrdup(profiles[i]) : NULL; data->flags = flags[i]; switch (method[i]) { case pa_method_equals: method_name[i] = "equals"; data->method = pa_classify_method_equals; data->arg.string = pa_xstrdup(arg[i]); break; case pa_method_startswith: method_name[i] = "startswidth"; data->method = pa_classify_method_startswith; data->arg.string = pa_xstrdup(arg[i]); break; case pa_method_matches: method_name[i] = "matches"; if (regcomp(&data->arg.rexp, arg[i], 0) == 0) { data->method = pa_classify_method_matches; break; } /* intentional fall trough */ default: pa_log("%s: invalid card definition %s", __FUNCTION__, type); memset(d, 0, sizeof(*d)); return; } } cards->ndef++; pa_log_info("card '%s' added (%s|%s|%s|0x%04x)", type, method_name[0], arg[0], d->data[0].profile ? d->data[0].profile : "", d->data[0].flags); if (d->data[1].profile) pa_log_info(" :: added (%s|%s|%s|0x%04x)", method_name[1], arg[1], d->data[1].profile ? d->data[1].profile : "", d->data[1].flags); }
/* This is called whenever new data may is available */ static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { pa_assert(s); pa_assert(length > 0); if (raw) { pa_assert(!sndfile); if (stdio_event) mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT); while (pa_stream_readable_size(s) > 0) { const void *data; if (pa_stream_peek(s, &data, &length) < 0) { pa_log(_("pa_stream_peek() failed: %s"), pa_strerror(pa_context_errno(context))); quit(1); return; } pa_assert(data); pa_assert(length > 0); if (buffer) { buffer = pa_xrealloc(buffer, buffer_length + length); memcpy((uint8_t*) buffer + buffer_length, data, length); buffer_length += length; } else { buffer = pa_xmalloc(length); memcpy(buffer, data, length); buffer_length = length; buffer_index = 0; } pa_stream_drop(s); } } else { pa_assert(sndfile); while (pa_stream_readable_size(s) > 0) { sf_count_t bytes; const void *data; if (pa_stream_peek(s, &data, &length) < 0) { pa_log(_("pa_stream_peek() failed: %s"), pa_strerror(pa_context_errno(context))); quit(1); return; } pa_assert(data); pa_assert(length > 0); if (writef_function) { size_t k = pa_frame_size(&sample_spec); if ((bytes = writef_function(sndfile, data, (sf_count_t) (length/k))) > 0) bytes *= (sf_count_t) k; } else bytes = sf_write_raw(sndfile, data, (sf_count_t) length); if (bytes < (sf_count_t) length) quit(1); pa_stream_drop(s); } } }
/* This is called whenever new data may is available */ static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { pa_assert(s); pa_assert(length > 0); if (raw) { pa_assert(!sndfile); if (stdio_event) mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT); while (pa_stream_readable_size(s) > 0) { const void *data; if (pa_stream_peek(s, &data, &length) < 0) { pa_log(_("pa_stream_peek() failed: %s"), pa_strerror(pa_context_errno(context))); quit(1); return; } pa_assert(length > 0); /* If there is a hole in the stream, we generate silence, except * if it's a passthrough stream in which case we skip the hole. */ if (data || !(flags & PA_STREAM_PASSTHROUGH)) { buffer = pa_xrealloc(buffer, buffer_length + length); if (data) memcpy((uint8_t *) buffer + buffer_length, data, length); else pa_silence_memory((uint8_t *) buffer + buffer_length, length, &sample_spec); buffer_length += length; } pa_stream_drop(s); } } else { pa_assert(sndfile); while (pa_stream_readable_size(s) > 0) { sf_count_t bytes; const void *data; if (pa_stream_peek(s, &data, &length) < 0) { pa_log(_("pa_stream_peek() failed: %s"), pa_strerror(pa_context_errno(context))); quit(1); return; } pa_assert(length > 0); if (!data && (flags & PA_STREAM_PASSTHROUGH)) { pa_stream_drop(s); continue; } if (!data && length > silence_buffer_length) { silence_buffer = pa_xrealloc(silence_buffer, length); pa_silence_memory((uint8_t *) silence_buffer + silence_buffer_length, length - silence_buffer_length, &sample_spec); silence_buffer_length = length; } if (writef_function) { size_t k = pa_frame_size(&sample_spec); if ((bytes = writef_function(sndfile, data ? data : silence_buffer, (sf_count_t) (length/k))) > 0) bytes *= (sf_count_t) k; } else bytes = sf_write_raw(sndfile, data ? data : silence_buffer, (sf_count_t) length); if (bytes < (sf_count_t) length) quit(1); pa_stream_drop(s); } } }