/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/* Drop root rights when called SUID root */
void pa_drop_root(void) {
uid_t uid = getuid();
-
+
if (uid == 0 || geteuid() != 0)
return;
if (cap_set_proc(caps) < 0)
goto fail;
- pa_log_info("dropped capabilities successfully.");
-
+ pa_log_info("dropped capabilities successfully.");
+
r = 0;
fail:
cap_free (caps);
-
+
return r;
}
pa_log("failed to drop capabilities: %s", pa_cstrerror(errno));
goto fail;
}
-
+
r = 0;
fail:
cap_free (caps);
-
+
return r;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
e++;
else
e = argv0;
-
+
printf("%s [options]\n\n"
"COMMANDS:\n"
" -h, --help Show this help\n"
" --scache-idle-time=SECS Unload autoloaded samples when idle and\n"
" this time passed\n"
" --log-level[=LEVEL] Increase or set verbosity level\n"
- " -v Increase the verbosity level\n"
+ " -v Increase the verbosity level\n"
" --log-target={auto,syslog,stderr} Specify the log target\n"
" -p, --dl-search-path=PATH Set the search path for dynamic shared\n"
" objects (plugins)\n"
" -F, --file=FILENAME Run the specified script\n"
" -C Open a command line on the running TTY\n"
" after startup\n\n"
-
+
" -n Don't load default script file\n", e);
}
if (conf->script_commands)
pa_strbuf_puts(buf, conf->script_commands);
-
+
while ((c = getopt_long(argc, argv, "L:F:ChDnp:kv", long_options, NULL)) != -1) {
switch (c) {
case ARG_HELP:
case ARG_CHECK:
conf->cmd = PA_CMD_CHECK;
break;
-
+
case ARG_LOAD:
case 'L':
pa_strbuf_printf(buf, "load-module %s\n", optarg);
break;
-
+
case ARG_FILE:
case 'F':
pa_strbuf_printf(buf, ".include %s\n", optarg);
break;
-
+
case 'C':
pa_strbuf_puts(buf, "load-module module-cli exit_on_eof=1\n");
break;
-
+
case ARG_DAEMONIZE:
case 'D':
if ((conf->daemonize = optarg ? pa_parse_boolean(optarg) : 1) < 0) {
if (conf->log_level < PA_LOG_LEVEL_MAX-1)
conf->log_level++;
}
-
+
break;
case ARG_HIGH_PRIORITY:
goto fail;
}
break;
-
+
case 'p':
case ARG_DL_SEARCH_PATH:
pa_xfree(conf->dl_search_path);
conf->dl_search_path = *optarg ? pa_xstrdup(optarg) : NULL;
break;
-
+
case 'n':
pa_xfree(conf->default_script_file);
conf->default_script_file = NULL;
goto fail;
}
break;
-
+
default:
goto fail;
}
}
*d = optind;
-
+
return 0;
-
+
fail:
if (buf)
pa_strbuf_free(buf);
-
+
return -1;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
static struct sigaction sigaction_prev;
/* Nonzero after pa_cpu_limit_init() */
-static int installed = 0;
+static int installed = 0;
/* The current state of operation */
static enum {
snprintf(t, sizeof(t), "Using %0.1f%% CPU\n", (double)CPUTIME_INTERVAL_SOFT/(now-last_time)*100);
write_err(t);
#endif
-
+
if (CPUTIME_INTERVAL_SOFT >= ((now-last_time)*(double)CPUTIME_PERCENT/100)) {
static const char c = 'X';
write_err("Soft CPU time limit exhausted, terminating.\n");
-
+
/* Try a soft cleanup */
write(the_pipe[1], &c, sizeof(c));
phase = PHASE_SOFT;
reset_cpu_time(CPUTIME_INTERVAL_HARD);
-
+
} else {
/* Everything's fine */
reset_cpu_time(CPUTIME_INTERVAL_SOFT);
last_time = now;
}
-
+
} else if (phase == PHASE_SOFT) {
write_err("Hard CPU time limit exhausted, terminating forcibly.\n");
_exit(1); /* Forced exit */
int pa_cpu_limit_init(pa_mainloop_api *m) {
struct sigaction sa;
assert(m && !api && !io_event && the_pipe[0] == -1 && the_pipe[1] == -1 && !installed);
-
+
time(&last_time);
/* Prepare the main loop pipe */
sa.sa_handler = signal_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
-
+
if (sigaction(SIGXCPU, &sa, &sigaction_prev) < 0) {
pa_cpu_limit_done();
return -1;
installed = 1;
reset_cpu_time(CPUTIME_INTERVAL_SOFT);
-
+
return 0;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
int r = -1;
FILE *f = NULL;
-
+
pa_config_item table[] = {
{ "daemonize", pa_config_parse_bool, NULL },
{ "fail", pa_config_parse_bool, NULL },
#endif
{ NULL, NULL, NULL },
};
-
+
table[0].data = &c->daemonize;
table[1].data = &c->fail;
table[2].data = &c->high_priority;
table[24].data = &c->rlimit_memlock;
#endif
#endif
-
-
+
+
pa_xfree(c->config_file);
c->config_file = NULL;
}
r = f ? pa_config_parse(c->config_file, f, table, NULL) : 0;
-
+
finish:
if (f)
fclose(f);
-
+
return r;
}
pa_strbuf_printf(s, "### Read from configuration file: %s ###\n", c->config_file);
assert(c->log_level <= PA_LOG_LEVEL_MAX);
-
+
pa_strbuf_printf(s, "daemonize = %i\n", !!c->daemonize);
pa_strbuf_printf(s, "fail = %i\n", !!c->fail);
pa_strbuf_printf(s, "high-priority = %i\n", !!c->high_priority);
pa_strbuf_printf(s, "rlimit-memlock = %li\n", c->rlimit_memlock.is_set ? (long int) c->rlimit_memlock.value : -1);
#endif
#endif
-
+
return pa_strbuf_tostring_free(s);
}
pa_log_level_t log_level;
int resample_method;
char *config_file;
-
+
#ifdef HAVE_SYS_RESOURCE_H
pa_rlimit rlimit_as, rlimit_core, rlimit_data, rlimit_fsize, rlimit_nofile, rlimit_stack;
#ifdef RLIMIT_NPROC
pa_rlimit rlimit_memlock;
#endif
#endif
-
+
} pa_daemon_conf;
/* Allocate a new structure and fill it with sane defaults */
static void long_info(const char *name, const char *path, pa_modinfo *i) {
static int nl = 0;
assert(name && i);
-
+
if (nl)
printf("\n");
nl = 1;
printf("Name: %s\n", name);
-
+
if (!i->description && !i->version && !i->author && !i->usage)
printf("No module information available\n");
else {
if (i->usage)
printf("Usage: %s\n", i->usage);
}
-
+
if (path)
printf("Path: %s\n", path);
}
static void show_info(const char *name, const char *path, void (*info)(const char *name, const char *path, pa_modinfo*i)) {
pa_modinfo *i;
-
+
if ((i = pa_modinfo_get_by_name(path ? path : name))) {
info(name, path, i);
pa_modinfo_free(i);
for (l = lt_preloaded_symbols; l->name; l++) {
char buf[64], *e;
-
+
if (l->address)
continue;
-
+
snprintf(buf, sizeof(buf), "%s", l->name);
if ((e = strrchr(buf, '.')))
*e = 0;
if (is_preloaded(e))
return 0;
-
+
show_info(e, path, c->log_level >= PA_LOG_INFO ? long_info : short_info);
return 0;
}
for (l = lt_preloaded_symbols; l->name; l++) {
char buf[64], *e;
-
+
if (l->address)
continue;
if (strlen(l->name) <= sizeof(PREFIX)-1 || strncmp(l->name, PREFIX, sizeof(PREFIX)-1))
continue;
-
+
snprintf(buf, sizeof(buf), "%s", l->name);
if ((e = strrchr(buf, '.')))
*e = 0;
-
+
show_info(buf, NULL, c->log_level >= PA_LOG_INFO ? long_info : short_info);
}
-
+
lt_dlforeachfile(NULL, callback, c);
}
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_module_load(userdata, "module-cli", NULL);
break;
#endif
-
+
#ifdef SIGUSR2
case SIGUSR2:
pa_module_load(userdata, "module-cli-protocol-unix", NULL);
/* This function is called only in system-wide mode. It creates a
* runtime dir in /var/run/ with proper UID/GID and drops privs
* afterwards. */
-
+
if (!(pw = getpwnam(PA_SYSTEM_USER))) {
pa_log("Failed to find user '%s'.", PA_SYSTEM_USER);
return -1;
pa_log("Failed to create '%s': %s", PA_SYSTEM_RUNTIME_PATH, pa_cstrerror(errno));
return -1;
}
-
+
if (initgroups(PA_SYSTEM_USER, gr->gr_gid) != 0) {
pa_log("Failed to change group list: %s", pa_cstrerror(errno));
return -1;
/* This function is called only when the daemon is started in
* per-user mode. We create the runtime directory somewhere in
* /tmp/ with the current UID/GID */
-
+
if (pa_make_secure_dir(fn, 0700, (uid_t)-1, (gid_t)-1) < 0) {
pa_log("Failed to create '%s': %s", fn, pa_cstrerror(errno));
return -1;
pa_daemon_conf *conf = NULL;
pa_mainloop *mainloop = NULL;
- char *s;
+ char *s;
int r, retval = 1, d = 0;
int daemon_pipe[2] = { -1, -1 };
int suid_root, real_root;
#ifdef HAVE_GETUID
real_root = getuid() == 0;
suid_root = !real_root && geteuid() == 0;
-
+
if (suid_root && (pa_own_uid_in_group(PA_REALTIME_GROUP, &gid) <= 0 || gid >= 1000)) {
pa_log_warn("WARNING: called SUID root, but not in group '"PA_REALTIME_GROUP"'.");
pa_drop_root();
real_root = 0;
suid_root = 0;
#endif
-
+
LTDL_SET_PRELOADED_SYMBOLS();
-
+
r = lt_dlinit();
assert(r == 0);
#endif
pa_random_seed();
-
+
pa_log_set_ident("pulseaudio");
-
+
conf = pa_daemon_conf_new();
-
+
if (pa_daemon_conf_load(conf, NULL) < 0)
goto finish;
pa_log("failed to kill daemon.");
else
retval = 0;
-
+
goto finish;
-
+
default:
assert(conf->cmd == PA_CMD_DAEMON);
}
pa_log("failed to create pipe.");
goto finish;
}
-
+
if ((child = fork()) < 0) {
pa_log("fork() failed: %s", pa_cstrerror(errno));
goto finish;
pa_log("daemon startup failed.");
else
pa_log_info("daemon startup successful.");
-
+
goto finish;
}
#ifdef SIGTSTP
signal(SIGTSTP, SIG_IGN);
#endif
-
+
#ifdef TIOCNOTTY
if ((tty_fd = open("/dev/tty", O_RDWR)) >= 0) {
ioctl(tty_fd, TIOCNOTTY, (char*) 0);
chdir("/");
umask(0022);
-
+
if (conf->system_instance) {
if (change_user() < 0)
goto finish;
} else if (create_runtime_dir() < 0)
goto finish;
-
+
if (conf->use_pid_file) {
if (pa_pid_file_create() < 0) {
pa_log("pa_pid_file_create() failed.");
#ifdef HAVE_SYS_RESOURCE_H
set_all_rlimits(conf);
#endif
-
+
#ifdef SIGPIPE
signal(SIGPIPE, SIG_IGN);
#endif
#ifdef SIGHUP
pa_signal_new(SIGHUP, signal_callback, c);
#endif
-
+
#ifdef OS_IS_WIN32
timer = pa_mainloop_get_api(mainloop)->time_new(
pa_mainloop_get_api(mainloop), pa_gettimeofday(&tv), message_cb, NULL);
r = pa_cpu_limit_init(pa_mainloop_get_api(mainloop));
assert(r == 0);
}
-
+
buf = pa_strbuf_new();
if (conf->default_script_file)
r = pa_cli_command_execute_file(c, conf->default_script_file, buf, &conf->fail);
r = pa_cli_command_execute(c, conf->script_commands, buf, &conf->fail);
pa_log_error("%s", s = pa_strbuf_tostring_free(buf));
pa_xfree(s);
-
+
if (r < 0 && conf->fail) {
pa_log("failed to initialize daemon.");
#ifdef HAVE_FORK
if (!conf->no_cpu_limit)
pa_cpu_limit_done();
-
+
pa_signal_done();
-
+
pa_log_info("Daemon terminated.");
-
+
finish:
if (mainloop)
if (valid_pid_file)
pa_pid_file_remove();
-
+
close_pipe(daemon_pipe);
#ifdef OS_IS_WIN32
#endif
lt_dlexit();
-
+
return retval;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
};
int i, ret;
-
+
assert(pcm_handle);
assert(f);
if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
return ret;
-
+
try_auto:
for (i = 0; try_order[i] != PA_SAMPLE_INVALID; i++) {
*f = try_order[i];
-
+
if ((ret = snd_pcm_hw_params_set_format(pcm_handle, hwparams, format_trans[*f])) >= 0)
return ret;
}
unsigned int c = ss->channels;
pa_sample_format_t f = ss->format;
snd_pcm_hw_params_t *hwparams;
-
+
assert(pcm_handle);
assert(ss);
assert(periods);
assert(period_size);
buffer_size = *periods * *period_size;
-
+
if ((ret = snd_pcm_hw_params_malloc(&hwparams)) < 0 ||
(ret = snd_pcm_hw_params_any(pcm_handle, hwparams)) < 0 ||
(ret = snd_pcm_hw_params_set_rate_resample(pcm_handle, hwparams, 0)) < 0 ||
pa_log_warn("device doesn't support sample format %s, changed to %s.", pa_sample_format_to_string(ss->format), pa_sample_format_to_string(f));
ss->format = f;
}
-
+
if ((ret = snd_pcm_prepare(pcm_handle)) < 0)
goto finish;
if ((ret = snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size)) < 0 ||
(ret = snd_pcm_hw_params_get_period_size(hwparams, period_size, NULL)) < 0)
goto finish;
-
+
assert(buffer_size > 0);
assert(*period_size > 0);
*periods = buffer_size / *period_size;
assert(*periods > 0);
-
+
ret = 0;
-
+
finish:
if (hwparams)
snd_pcm_hw_params_free(hwparams);
-
+
return ret;
}
if (fallback) {
snd_mixer_selem_id_set_name(sid, fallback);
-
+
if (!(elem = snd_mixer_find_selem(mixer, sid)))
pa_log_warn("Cannot find fallback mixer control \"%s\".", snd_mixer_selem_id_get_name(sid));
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
static void clear_up(struct userdata *u) {
assert(u);
-
+
if (u->sink) {
pa_sink_disconnect(u->sink);
pa_sink_unref(u->sink);
u->sink = NULL;
}
-
+
if (u->pcm_fdl)
pa_alsa_fdlist_free(u->pcm_fdl);
if (u->mixer_fdl)
snd_mixer_close(u->mixer_handle);
u->mixer_handle = NULL;
}
-
+
if (u->pcm_handle) {
snd_pcm_drop(u->pcm_handle);
snd_pcm_close(u->pcm_handle);
assert(u);
pa_log_info("*** ALSA-XRUN (playback) ***");
-
+
if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0) {
pa_log("snd_pcm_prepare() failed: %s", snd_strerror(-ret));
assert(u);
update_usage(u);
-
+
for (;;) {
pa_memchunk *memchunk = NULL;
snd_pcm_sframes_t frames;
-
+
if (u->memchunk.memblock)
memchunk = &u->memchunk;
else {
else
memchunk = &u->memchunk;
}
-
+
assert(memchunk->memblock && memchunk->memblock->data && memchunk->length && memchunk->memblock->length && (memchunk->length % u->frame_size) == 0);
if ((frames = snd_pcm_writei(u->pcm_handle, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length / u->frame_size)) < 0) {
if (frames == -EPIPE) {
if (xrun_recovery(u) < 0)
return;
-
+
continue;
}
memchunk->index = memchunk->length = 0;
}
}
-
+
break;
}
}
struct userdata *u = s->userdata;
snd_pcm_sframes_t frames;
int err;
-
+
assert(s && u && u->sink);
if ((err = snd_pcm_delay(u->pcm_handle, &frames)) < 0) {
for (i = 0; i < s->hw_volume.channels; i++) {
long alsa_vol;
-
+
assert(snd_mixer_selem_has_playback_channel(u->mixer_elem, i));
vol = s->hw_volume.values[i];
if (vol > PA_VOLUME_NORM)
vol = PA_VOLUME_NORM;
-
+
alsa_vol = (long) roundf(((float) vol * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
if ((err = snd_mixer_selem_set_playback_volume(u->mixer_elem, i, alsa_vol)) < 0)
const char *name;
char *name_buf = NULL;
int namereg_fail;
-
+
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
pa_log("failed to parse module arguments");
goto fail;
}
frame_size = pa_frame_size(&ss);
-
+
/* Fix latency to 100ms */
periods = 8;
fragsize = pa_bytes_per_second(&ss)/128;
goto fail;
}
period_size = fragsize/frame_size;
-
+
u = pa_xnew0(struct userdata, 1);
m->userdata = u;
u->module = m;
-
+
snd_config_update_free_global();
if ((err = snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)) < 0) {
pa_log("Error opening PCM device %s: %s", dev, snd_strerror(err));
if (ss.channels != map.channels)
/* Seems ALSA didn't like the channel number, so let's fix the channel map */
pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_ALSA);
-
+
if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0) {
pa_log("Error opening mixer: %s", snd_strerror(err));
goto fail;
snd_mixer_elem_set_callback_private(u->mixer_elem, u);
} else
u->mixer_fdl = NULL;
-
+
u->frame_size = frame_size;
u->fragment_size = period_size * frame_size;
u->memchunk.memblock = NULL;
u->memchunk.index = u->memchunk.length = 0;
-
+
ret = 0;
/* Get initial mixer settings */
u->sink->get_hw_volume(u->sink);
if (u->sink->get_hw_mute)
u->sink->get_hw_mute(u->sink);
-
+
finish:
pa_xfree(name_buf);
-
+
if (ma)
pa_modargs_free(ma);
if (pcm_info)
snd_pcm_info_free(pcm_info);
-
+
return ret;
fail:
-
+
if (u)
pa__done(c, m);
pa_memblock_unref(u->memchunk.memblock);
if (u->silence.memblock)
pa_memblock_unref(u->silence.memblock);
-
+
pa_xfree(u);
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
static void clear_up(struct userdata *u) {
assert(u);
-
+
if (u->source) {
pa_source_disconnect(u->source);
pa_source_unref(u->source);
u->source = NULL;
}
-
+
if (u->pcm_fdl)
pa_alsa_fdlist_free(u->pcm_fdl);
if (u->mixer_fdl)
snd_mixer_close(u->mixer_handle);
u->mixer_handle = NULL;
}
-
+
if (u->pcm_handle) {
snd_pcm_drop(u->pcm_handle);
snd_pcm_close(u->pcm_handle);
assert(u);
pa_log_info("*** ALSA-XRUN (capture) ***");
-
+
if ((ret = snd_pcm_prepare(u->pcm_handle)) < 0) {
pa_log("snd_pcm_prepare() failed: %s", snd_strerror(-ret));
assert(u);
update_usage(u);
-
+
for (;;) {
pa_memchunk post_memchunk;
snd_pcm_sframes_t frames;
size_t l;
-
+
if (!u->memchunk.memblock) {
u->memchunk.memblock = pa_memblock_new(u->source->core->mempool, u->memchunk.length = u->fragment_size);
u->memchunk.index = 0;
}
-
+
assert(u->memchunk.memblock);
assert(u->memchunk.length);
assert(u->memchunk.memblock->data);
if ((frames = snd_pcm_readi(u->pcm_handle, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length / u->frame_size)) < 0) {
if (frames == -EAGAIN)
return;
-
+
if (frames == -EPIPE) {
if (xrun_recovery(u) < 0)
return;
-
+
continue;
}
}
l = frames * u->frame_size;
-
+
post_memchunk = u->memchunk;
post_memchunk.length = l;
u->memchunk.index += l;
u->memchunk.length -= l;
-
+
if (u->memchunk.length == 0) {
pa_memblock_unref(u->memchunk.memblock);
u->memchunk.memblock = NULL;
u->memchunk.index = u->memchunk.length = 0;
}
-
+
break;
}
}
u->source->get_hw_volume(u->source);
if (u->source->get_hw_mute)
u->source->get_hw_mute(u->source);
-
+
pa_subscription_post(u->source->core,
PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE,
u->source->index);
for (i = 0;i < s->hw_volume.channels;i++) {
long set_vol;
-
+
assert(snd_mixer_selem_has_capture_channel(u->mixer_elem, i));
-
+
if ((err = snd_mixer_selem_get_capture_volume(u->mixer_elem, i, &vol)) < 0)
goto fail;
set_vol = (long) roundf(((float) s->hw_volume.values[i] * (u->hw_volume_max - u->hw_volume_min)) / PA_VOLUME_NORM) + u->hw_volume_min;
-
+
/* Try to avoid superfluous volume changes */
if (set_vol != vol)
s->hw_volume.values[i] = (pa_volume_t) roundf(((float) (vol - u->hw_volume_min) * PA_VOLUME_NORM) / (u->hw_volume_max - u->hw_volume_min));
const char *name;
char *name_buf = NULL;
int namereg_fail;
-
+
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
pa_log("failed to parse module arguments");
goto fail;
/* Fix latency to 100ms */
periods = 12;
fragsize = pa_bytes_per_second(&ss)/128;
-
+
if (pa_modargs_get_value_u32(ma, "fragments", &periods) < 0 || pa_modargs_get_value_u32(ma, "fragment_size", &fragsize) < 0) {
pa_log("failed to parse buffer metrics");
goto fail;
}
period_size = fragsize/frame_size;
-
+
u = pa_xnew0(struct userdata, 1);
m->userdata = u;
u->module = m;
-
+
snd_config_update_free_global();
if ((err = snd_pcm_open(&u->pcm_handle, dev = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)) < 0) {
pa_log("Error opening PCM device %s: %s", dev, snd_strerror(err));
name = name_buf = pa_sprintf_malloc("alsa_input.%s", dev);
namereg_fail = 0;
}
-
+
if (!(u->source = pa_source_new(c, __FILE__, name, namereg_fail, &ss, &map))) {
pa_log("Failed to create source object");
goto fail;
u->memchunk.index = u->memchunk.length = 0;
snd_pcm_start(u->pcm_handle);
-
+
ret = 0;
/* Get initial mixer settings */
if (pcm_info)
snd_pcm_info_free(pcm_info);
-
+
return ret;
fail:
-
+
if (u)
pa__done(c, m);
return;
clear_up(u);
-
+
if (u->memchunk.memblock)
pa_memblock_unref(u->memchunk.memblock);
-
+
pa_xfree(u);
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
static void eof_and_unload_cb(pa_cli*c, void *userdata) {
pa_module *m = userdata;
-
+
assert(c);
assert(m);
pa_iochannel *io;
pa_modargs *ma;
int exit_on_eof = 0;
-
+
assert(c);
assert(m);
pa_log("failed to parse module arguments.");
goto fail;
}
-
+
if (pa_modargs_get_value_boolean(ma, "exit_on_eof", &exit_on_eof) < 0) {
pa_log("exit_on_eof= expects boolean argument.");
goto fail;
pa_cli_set_eof_callback(m->userdata, exit_on_eof ? eof_and_exit_cb : eof_and_unload_cb, m);
pa_modargs_free(ma);
-
+
return 0;
fail:
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
struct output *master;
pa_time_event *time_event;
uint32_t adjust_time;
-
+
PA_LLIST_HEAD(struct output, outputs);
};
for (o = u->outputs; o; o = o->next) {
uint32_t sink_latency = o->sink_input->sink ? pa_sink_get_latency(o->sink_input->sink) : 0;
-
+
o->total_latency = sink_latency + pa_sink_input_get_latency(o->sink_input);
-
+
if (sink_latency > max_sink_latency)
max_sink_latency = sink_latency;
assert(min_total_latency != (pa_usec_t) -1);
target_latency = max_sink_latency > min_total_latency ? max_sink_latency : min_total_latency;
-
+
pa_log_info("[%s] target latency is %0.0f usec.", u->sink->name, (float) target_latency);
base_rate = u->sink->sample_spec.rate;
for (o = u->outputs; o; o = o->next) {
- uint32_t r = base_rate;
-
+ uint32_t r = base_rate;
+
if (o->total_latency < target_latency)
r -= (uint32_t) (((((double) target_latency - o->total_latency))/u->adjust_time)*r/ 1000000);
else if (o->total_latency > target_latency)
assert(u && u->sink);
update_usage(u);
-
+
if (pa_sink_render(u->sink, RENDER_SIZE, &chunk) < 0)
return;
if (pa_memblockq_peek(o->memblockq, chunk) >= 0)
return 0;
-
+
/* Try harder */
request_memblock(o->userdata);
-
+
return pa_memblockq_peek(o->memblockq, chunk);
}
static pa_usec_t sink_input_get_latency_cb(pa_sink_input *i) {
struct output *o = i->userdata;
assert(i && o && o->sink_input);
-
+
return pa_bytes_to_usec(pa_memblockq_get_length(o->memblockq), &i->sample_spec);
}
static void sink_notify(pa_sink *s) {
struct userdata *u;
struct output *o;
-
+
assert(s);
u = s->userdata;
assert(u);
-
+
for (o = u->outputs; o; o = o->next)
pa_sink_notify(o->sink_input->sink);
}
struct output *o = NULL;
char t[256];
pa_sink_input_new_data data;
-
+
assert(u && sink && u->sink);
-
+
o = pa_xmalloc(sizeof(struct output));
o->userdata = u;
-
+
o->counter = 0;
o->memblockq = pa_memblockq_new(
0,
pa_sink_input_new_data_set_sample_spec(&data, &u->sink->sample_spec);
pa_sink_input_new_data_set_channel_map(&data, &u->sink->channel_map);
data.module = u->module;
-
+
if (!(o->sink_input = pa_sink_input_new(u->core, &data, PA_SINK_INPUT_VARIABLE_RATE)))
goto fail;
o->sink_input->drop = sink_input_drop_cb;
o->sink_input->kill = sink_input_kill_cb;
o->sink_input->userdata = o;
-
+
PA_LLIST_PREPEND(struct output, u->outputs, o);
u->n_outputs++;
return o;
if (o->memblockq)
pa_memblockq_free(o->memblockq);
-
+
pa_xfree(o);
}
static void clear_up(struct userdata *u) {
struct output *o;
assert(u);
-
+
if (u->time_event) {
u->core->mainloop->time_free(u->time_event);
u->time_event = NULL;
}
-
+
while ((o = u->outputs))
output_free(o);
u->master = NULL;
-
+
if (u->sink) {
pa_sink_disconnect(u->sink);
pa_sink_unref(u->sink);
int resample_method = -1;
pa_sample_spec ss;
pa_channel_map map;
-
+
assert(c && m);
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
goto fail;
}
}
-
+
u = pa_xnew(struct userdata, 1);
m->userdata = u;
u->sink = NULL;
pa_log("failed to parse adjust_time value");
goto fail;
}
-
+
if (!(master_name = pa_modargs_get_value(ma, "master", NULL)) || !(slaves = pa_modargs_get_value(ma, "slaves", NULL))) {
pa_log("no master or slave sinks specified");
goto fail;
pa_log("channel map and sample specification don't match.");
goto fail;
}
-
+
if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) {
pa_log("failed to create sink");
goto fail;
u->sink->get_latency = sink_get_latency_cb;
u->sink->notify = sink_notify;
u->sink->userdata = u;
-
+
if (!(u->master = output_new(u, master_sink, resample_method))) {
pa_log("failed to create master sink input on sink '%s'.", u->sink->name);
goto fail;
}
-
+
split_state = NULL;
while ((n = pa_split(slaves, ",", &split_state))) {
pa_sink *slave_sink;
-
+
if (!(slave_sink = pa_namereg_get(c, n, PA_NAMEREG_SINK, 1))) {
pa_log("invalid slave sink '%s'", n);
goto fail;
goto fail;
}
}
-
+
if (u->n_outputs <= 1)
pa_log_warn("WARNING: no slave sinks specified.");
tv.tv_sec += u->adjust_time;
u->time_event = c->mainloop->time_new(c->mainloop, &tv, time_callback, u);
}
-
+
pa_modargs_free(ma);
- return 0;
+ return 0;
fail:
pa_xfree(n);
-
+
if (ma)
pa_modargs_free(ma);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
if (errno != ENOENT)
pa_log_error("open(\"/proc/asound/devices\") failed: %s", pa_cstrerror(errno));
-
+
return -1;
}
char line[64], args[64];
unsigned device, subdevice;
int is_sink;
-
+
if (!fgets(line, sizeof(line), f))
break;
if (just_one && is_sink && n_sink >= 1)
continue;
-
+
if (just_one && !is_sink && n_source >= 1)
continue;
}
fclose(f);
-
+
return n;
}
#endif
static int detect_oss(pa_core *c, int just_one) {
FILE *f;
int n = 0, b = 0;
-
+
if (!(f = fopen("/dev/sndstat", "r")) &&
!(f = fopen("/proc/sndstat", "r")) &&
!(f = fopen("/proc/asound/oss/sndstat", "r"))) {
while (!feof(f)) {
char line[64], args[64];
unsigned device;
-
+
if (!fgets(line, sizeof(line), f))
break;
if (line[0] == 0)
break;
-
+
if (sscanf(line, "%u: ", &device) == 1) {
if (device == 0)
snprintf(args, sizeof(args), "device=/dev/dsp");
else
snprintf(args, sizeof(args), "device=/dev/dsp%u", device);
-
+
if (!pa_module_load(c, "module-oss", args))
continue;
-
+
} else if (sscanf(line, "pcm%u: ", &device) == 1) {
/* FreeBSD support, the devices are named /dev/dsp0.0, dsp0.1 and so on */
snprintf(args, sizeof(args), "device=/dev/dsp%u.0", device);
-
+
if (!pa_module_load(c, "module-oss", args))
continue;
}
"just-one",
NULL
};
-
+
assert(c);
assert(m);
pa_log("Failed to parse module arguments");
goto fail;
}
-
+
if (pa_modargs_get_value_boolean(ma, "just-one", &just_one) < 0) {
pa_log("just_one= expects a boolean argument.");
goto fail;
}
#if HAVE_ALSA
- if ((n = detect_alsa(c, just_one)) <= 0)
+ if ((n = detect_alsa(c, just_one)) <= 0)
#endif
#if HAVE_OSS
if ((n = detect_oss(c, just_one)) <= 0)
}
pa_log_info("loaded %i modules.", n);
-
+
/* We were successful and can unload ourselves now. */
pa_module_unload_request(m);
fail:
if (ma)
pa_modargs_free(ma);
-
+
return -1;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
void *write_data;
size_t write_length, write_index;
-
+
void *read_data;
size_t read_length, read_index;
u->write_index += r;
assert(u->write_index <= u->write_length);
-
+
if (u->write_index == u->write_length) {
free(u->write_data);
u->write_data = NULL;
}
} else if (u->state == STATE_RUNNING) {
pa_module_set_used(u->module, pa_sink_used_by(u->sink));
-
+
if (!u->memchunk.length)
if (pa_sink_render(u->sink, 8192, &u->memchunk) < 0)
return 0;
assert(u->memchunk.memblock && u->memchunk.length);
-
+
if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) {
pa_log("write() failed: %s", pa_cstrerror(errno));
return -1;
u->memchunk.index += r;
u->memchunk.length -= r;
-
+
if (u->memchunk.length <= 0) {
pa_memblock_unref(u->memchunk.memblock);
u->memchunk.memblock = NULL;
}
}
-
+
return 0;
}
assert(u->read_length >= sizeof(int32_t));
u->read_index = 0;
u->read_length = sizeof(int32_t);
-
+
break;
case STATE_LATENCY: {
pa_xfree(u->read_data);
u->read_data = NULL;
u->read_index = u->read_length = 0;
-
+
break;
}
-
+
default:
abort();
}
static int do_read(struct userdata *u) {
assert(u);
-
+
if (!pa_iochannel_is_readable(u->io))
return 0;
-
+
if (u->state == STATE_AUTH || u->state == STATE_LATENCY) {
ssize_t r;
-
+
if (!u->read_data)
return 0;
-
+
assert(u->read_index < u->read_length);
-
+
if ((r = pa_iochannel_read(u->io, (uint8_t*) u->read_data + u->read_index, u->read_length - u->read_index)) <= 0) {
pa_log("read() failed: %s", r < 0 ? pa_cstrerror(errno) : "EOF");
cancel(u);
assert(u);
u->core->mainloop->defer_enable(u->defer_event, 0);
-
+
if (do_read(u) < 0 || do_write(u) < 0)
cancel(u);
}
pa_socket_client_unref(u->client);
u->client = NULL;
-
+
if (!io) {
pa_log("connection failed: %s", pa_cstrerror(errno));
cancel(u);
return;
}
-
+
u->io = io;
pa_iochannel_set_callback(u->io, io_callback, u);
}
pa_sample_spec ss;
pa_modargs *ma = NULL;
char *t;
-
+
assert(c && m);
-
+
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
pa_log("failed to parse module arguments");
goto fail;
pa_log("esound sample type support is limited to mono/stereo and U8 or S16NE sample data");
goto fail;
}
-
+
u = pa_xmalloc0(sizeof(struct userdata));
u->core = c;
u->module = m;
/* Reserve space for the response */
u->read_data = pa_xmalloc(u->read_length = sizeof(int32_t));
-
+
u->sink->notify = notify_cb;
u->sink->get_latency = get_latency_cb;
u->sink->userdata = u;
u->defer_event = c->mainloop->defer_new(c->mainloop, defer_callback, u);
c->mainloop->defer_enable(u->defer_event, 0);
-
+
pa_modargs_free(ma);
-
+
return 0;
fail:
if (ma)
pa_modargs_free(ma);
-
+
pa__done(c, m);
return -1;
u->module = NULL;
cancel(u);
-
+
if (u->memchunk.memblock)
pa_memblock_unref(u->memchunk.memblock);
if (u->client)
pa_socket_client_unref(u->client);
-
+
pa_xfree(u->read_data);
pa_xfree(u->write_data);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
#endif
#ifdef HAVE_OSS
CAP_OSS,
-#endif
+#endif
CAP_MAX
} capability_t;
module_name = "module-alsa-source";
snprintf(args, sizeof(args), "device=hw:%u source_name=alsa_input.%s", card, strip_udi(udi));
}
-
+
return pa_module_load(u->core, module_name, args);
}
type = libhal_device_get_property_string(ctx, udi, "oss.type", error);
if (!type || dbus_error_is_set(error))
return FALSE;
-
+
if (!strcmp(type, "pcm")) {
char *e;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pthread_mutex_t mutex;
pthread_cond_t cond;
-
+
void * buffer[PA_CHANNELS_MAX];
jack_nframes_t frames_requested;
int quit_requested;
static void stop_sink(struct userdata *u) {
assert (u);
-
+
jack_client_close(u->client);
u->client = NULL;
u->core->mainloop->io_free(u->io_event);
static void io_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) {
struct userdata *u = userdata;
char x;
-
+
assert(m);
assert(e);
assert(flags == PA_IO_EVENT_INPUT);
assert(u->pipe_fds[0] == fd);
pa_read(fd, &x, 1, &u->pipe_fd_type);
-
+
if (u->quit_requested) {
stop_sink(u);
u->quit_requested = 0;
return;
}
-
+
pthread_mutex_lock(&u->mutex);
if (u->frames_requested > 0) {
unsigned fs;
jack_nframes_t frame_idx;
pa_memchunk chunk;
-
+
fs = pa_frame_size(&u->sink->sample_spec);
pa_sink_render_full(u->sink, u->frames_requested * fs, &chunk);
for (frame_idx = 0; frame_idx < u->frames_requested; frame_idx ++) {
unsigned c;
-
+
for (c = 0; c < u->channels; c++) {
float *s = ((float*) ((uint8_t*) chunk.memblock->data + chunk.index)) + (frame_idx * u->channels) + c;
float *d = ((float*) u->buffer[c]) + frame_idx;
-
+
*d = *s;
}
}
-
+
pa_memblock_unref(chunk.memblock);
u->frames_requested = 0;
-
+
pthread_cond_signal(&u->cond);
}
if (jack_transport_query(u->client, NULL) == JackTransportRolling) {
unsigned c;
-
+
pthread_mutex_lock(&u->mutex);
-
+
u->frames_requested = nframes;
-
+
for (c = 0; c < u->channels; c++) {
u->buffer[c] = jack_port_get_buffer(u->port[c], nframes);
assert(u->buffer[c]);
}
-
+
request_render(u);
-
+
pthread_cond_wait(&u->cond, &u->mutex);
u->frames_in_buffer = nframes;
u->timestamp = jack_get_current_transport_frame(u->client);
-
+
pthread_mutex_unlock(&u->mutex);
}
-
+
return 0;
}
static pa_usec_t sink_get_latency_cb(pa_sink *s) {
struct userdata *u;
jack_nframes_t n, l, d;
-
+
assert(s);
u = s->userdata;
-
+
if (jack_transport_query(u->client, NULL) != JackTransportRolling)
return 0;
if (d >= l)
return 0;
-
+
return pa_bytes_to_usec((l - d) * pa_frame_size(&s->sample_spec), &s->sample_spec);
}
unsigned i;
const char **ports = NULL, **p;
char *t;
-
+
assert(c);
assert(m);
jack_set_error_function(jack_error_func);
-
+
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
pa_log("failed to parse module arguments.");
goto fail;
pa_log("failed to parse connect= argument.");
goto fail;
}
-
+
server_name = pa_modargs_get_value(ma, "server_name", NULL);
client_name = pa_modargs_get_value(ma, "client_name", "PulseAudio");
pthread_mutex_init(&u->mutex, NULL);
pthread_cond_init(&u->cond, NULL);
-
+
if (pipe(u->pipe_fds) < 0) {
pa_log("pipe() failed: %s", pa_cstrerror(errno));
goto fail;
}
pa_make_nonblock_fd(u->pipe_fds[1]);
-
+
if (!(u->client = jack_client_open(client_name, server_name ? JackServerName : JackNullOption, &status, server_name))) {
pa_log("jack_client_open() failed.");
goto fail;
}
ports = jack_get_ports(u->client, NULL, NULL, JackPortIsPhysical|JackPortIsInput);
-
+
channels = 0;
for (p = ports; *p; p++)
channels++;
if (!channels)
channels = c->default_sample_spec.channels;
-
+
if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || channels <= 0 || channels >= PA_CHANNELS_MAX) {
pa_log("failed to parse channels= argument.");
goto fail;
pa_log("failed to parse channel_map= argument.");
goto fail;
}
-
+
pa_log_info("Successfully connected as '%s'", jack_get_client_name(u->client));
ss.channels = u->channels = channels;
}
pa_log_info("connecting %s to %s", jack_port_name(u->port[i]), *p);
-
+
if (jack_connect(u->client, jack_port_name(u->port[i]), *p)) {
pa_log("failed to connect %s to %s, leaving unconnected.", jack_port_name(u->port[i]), *p);
break;
}
u->io_event = c->mainloop->io_new(c->mainloop, u->pipe_fds[0], PA_IO_EVENT_INPUT, io_event_cb, u);
-
+
free(ports);
pa_modargs_free(ma);
-
+
return 0;
fail:
pa_modargs_free(ma);
free(ports);
-
+
pa__done(c, m);
return -1;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pthread_mutex_t mutex;
pthread_cond_t cond;
-
+
void * buffer[PA_CHANNELS_MAX];
jack_nframes_t frames_posted;
int quit_requested;
static void stop_source(struct userdata *u) {
assert (u);
-
+
jack_client_close(u->client);
u->client = NULL;
u->core->mainloop->io_free(u->io_event);
static void io_event_cb(pa_mainloop_api *m, pa_io_event *e, int fd, pa_io_event_flags_t flags, void *userdata) {
struct userdata *u = userdata;
char x;
-
+
assert(m);
assert(flags == PA_IO_EVENT_INPUT);
assert(u);
assert(u->pipe_fds[0] == fd);
pa_read(fd, &x, 1, &u->pipe_fd_type);
-
+
if (u->quit_requested) {
stop_source(u);
u->quit_requested = 0;
return;
}
-
+
pthread_mutex_lock(&u->mutex);
if (u->frames_posted > 0) {
unsigned fs;
jack_nframes_t frame_idx;
pa_memchunk chunk;
-
+
fs = pa_frame_size(&u->source->sample_spec);
chunk.memblock = pa_memblock_new(u->core->mempool, chunk.length = u->frames_posted * fs);
chunk.index = 0;
-
+
for (frame_idx = 0; frame_idx < u->frames_posted; frame_idx ++) {
unsigned c;
-
+
for (c = 0; c < u->channels; c++) {
float *s = ((float*) u->buffer[c]) + frame_idx;
float *d = ((float*) ((uint8_t*) chunk.memblock->data + chunk.index)) + (frame_idx * u->channels) + c;
-
+
*d = *s;
}
}
pa_memblock_unref(chunk.memblock);
u->frames_posted = 0;
-
+
pthread_cond_signal(&u->cond);
}
if (jack_transport_query(u->client, NULL) == JackTransportRolling) {
unsigned c;
-
+
pthread_mutex_lock(&u->mutex);
-
+
u->frames_posted = nframes;
-
+
for (c = 0; c < u->channels; c++) {
u->buffer[c] = jack_port_get_buffer(u->port[c], nframes);
assert(u->buffer[c]);
}
-
+
request_post(u);
-
+
pthread_cond_wait(&u->cond, &u->mutex);
u->frames_in_buffer = nframes;
u->timestamp = jack_get_current_transport_frame(u->client);
-
+
pthread_mutex_unlock(&u->mutex);
}
-
+
return 0;
}
static pa_usec_t source_get_latency_cb(pa_source *s) {
struct userdata *u;
jack_nframes_t n, l, d;
-
+
assert(s);
u = s->userdata;
-
+
if (jack_transport_query(u->client, NULL) != JackTransportRolling)
return 0;
d = n - u->timestamp;
l = jack_port_get_total_latency(u->client, u->port[0]);
-
+
return pa_bytes_to_usec((l + d) * pa_frame_size(&s->sample_spec), &s->sample_spec);
}
unsigned i;
const char **ports = NULL, **p;
char *t;
-
+
assert(c);
assert(m);
jack_set_error_function(jack_error_func);
-
+
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
pa_log("failed to parse module arguments.");
goto fail;
pa_log("failed to parse connect= argument.");
goto fail;
}
-
+
server_name = pa_modargs_get_value(ma, "server_name", NULL);
client_name = pa_modargs_get_value(ma, "client_name", "PulseAudio");
pthread_mutex_init(&u->mutex, NULL);
pthread_cond_init(&u->cond, NULL);
-
+
if (pipe(u->pipe_fds) < 0) {
pa_log("pipe() failed: %s", pa_cstrerror(errno));
goto fail;
}
pa_make_nonblock_fd(u->pipe_fds[1]);
-
+
if (!(u->client = jack_client_open(client_name, server_name ? JackServerName : JackNullOption, &status, server_name))) {
pa_log("jack_client_open() failed.");
goto fail;
}
ports = jack_get_ports(u->client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput);
-
+
channels = 0;
for (p = ports; *p; p++)
channels++;
if (!channels)
channels = c->default_sample_spec.channels;
-
+
if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || channels <= 0 || channels >= PA_CHANNELS_MAX) {
pa_log("failed to parse channels= argument.");
goto fail;
pa_log("failed to parse channel_map= argument.");
goto fail;
}
-
+
pa_log_info("Successfully connected as '%s'", jack_get_client_name(u->client));
ss.channels = u->channels = channels;
}
pa_log_info("connecting %s to %s", jack_port_name(u->port[i]), *p);
-
+
if (jack_connect(u->client, *p, jack_port_name(u->port[i]))) {
pa_log("failed to connect %s to %s, leaving unconnected.", jack_port_name(u->port[i]), *p);
break;
}
u->io_event = c->mainloop->io_new(c->mainloop, u->pipe_fds[0], PA_IO_EVENT_INPUT, io_event_cb, u);
-
+
free(ports);
pa_modargs_free(ma);
-
+
return 0;
fail:
pa_modargs_free(ma);
free(ports);
-
+
pa__done(c, m);
return -1;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_log("lost connection to LIRC daemon.");
goto fail;
}
-
+
if (events & PA_IO_EVENT_INPUT) {
char *c;
-
+
if (lirc_nextcode(&code) != 0 || !code) {
pa_log("lirc_nextcode() failed.");
goto fail;
}
-
+
c = pa_xstrdup(code);
c[strcspn(c, "\n\r")] = 0;
pa_log_debug("raw IR code '%s'", c);
pa_xfree(c);
-
+
while (lirc_code2char(u->config, code, &name) == 0 && name) {
enum {
INVALID,
RESET,
MUTE_TOGGLE
} volchange = INVALID;
-
+
pa_log_info("translated IR code '%s'", name);
-
+
if (strcasecmp(name, "volume-up") == 0)
volchange = UP;
else if (strcasecmp(name, "volume-down") == 0)
volchange = MUTE_TOGGLE;
else if (strcasecmp(name, "reset") == 0)
volchange = RESET;
-
+
if (volchange == INVALID)
pa_log_warn("recieved unknown IR code '%s'", name);
else {
pa_sink *s;
-
+
if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1)))
pa_log("failed to get sink '%s'", u->sink_name);
else {
pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv);
break;
-
+
case DOWN:
for (i = 0; i < cv.channels; i++) {
if (cv.values[i] >= DELTA)
else
cv.values[i] = PA_VOLUME_MUTED;
}
-
+
pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv);
break;
-
+
case MUTE:
pa_sink_set_mute(s, PA_MIXER_HARDWARE, 0);
break;
-
+
case RESET:
pa_sink_set_mute(s, PA_MIXER_HARDWARE, 1);
break;
-
+
case MUTE_TOGGLE:
pa_sink_set_mute(s, PA_MIXER_HARDWARE, !pa_sink_get_mute(s, PA_MIXER_HARDWARE));
pa_xfree(code);
return;
-
+
fail:
u->module->core->mainloop->io_free(u->io);
u->io = NULL;
free(code);
}
-
+
int pa__init(pa_core *c, pa_module*m) {
pa_modargs *ma = NULL;
struct userdata *u;
pa_log("module-lirc may no be loaded twice.");
return -1;
}
-
+
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
pa_log("Failed to parse module arguments");
goto fail;
pa_log("lirc_readconfig() failed.");
goto fail;
}
-
+
u->io = c->mainloop->io_new(c->mainloop, u->lirc_fd, PA_IO_EVENT_INPUT|PA_IO_EVENT_HANGUP, io_callback, u);
lirc_in_use = 1;
pa_modargs_free(ma);
-
+
return 0;
fail:
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
}
pa_lock_fd(fileno(f), 1);
-
+
while (!feof(f)) {
char *d, *v;
pa_volume_t volume;
regex_t regex;
char ln[256];
struct rule *rule;
-
+
if (!fgets(ln, sizeof(ln), f))
break;
n++;
-
+
pa_strip_nl(ln);
if (ln[0] == '#' || !*ln )
d = ln+strcspn(ln, WHITESPACE);
v = d+strspn(d, WHITESPACE);
-
+
if (!*v) {
pa_log(__FILE__ ": [%s:%u] failed to parse line - too few words", filename, n);
goto finish;
volume = (pa_volume_t) k;
-
+
if (regcomp(®ex, ln, REG_EXTENDED|REG_NOSUB) != 0) {
pa_log("[%s:%u] invalid regular expression", filename, n);
goto finish;
else
u->rules = rule;
end = rule;
-
+
*d = 0;
}
ret = 0;
-
+
finish:
if (f) {
pa_lock_fd(fileno(f), 0);
if (!si->name)
return;
-
+
for (r = u->rules; r; r = r->next) {
if (!regexec(&r->regex, si->name, 0, NULL, 0)) {
pa_cvolume cv;
u->rules = NULL;
u->subscription = NULL;
m->userdata = u;
-
+
if (load_rules(u, pa_modargs_get_value(ma, "table", NULL)) < 0)
goto fail;
if (u->subscription)
pa_subscription_free(u->subscription);
-
+
for (r = u->rules; r; r = n) {
n = r->next;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_log("lost connection to evdev device.");
goto fail;
}
-
+
if (events & PA_IO_EVENT_INPUT) {
struct input_event ev;
if (volchange != INVALID) {
pa_sink *s;
-
+
if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1)))
pa_log("failed to get sink '%s'", u->sink_name);
else {
int i;
pa_cvolume cv = *pa_sink_get_volume(s, PA_MIXER_HARDWARE);
-
+
#define DELTA (PA_VOLUME_NORM/20)
-
+
switch (volchange) {
case UP:
for (i = 0; i < cv.channels; i++) {
pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv);
break;
-
+
case DOWN:
for (i = 0; i < cv.channels; i++) {
if (cv.values[i] >= DELTA)
else
cv.values[i] = PA_VOLUME_MUTED;
}
-
+
pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv);
break;
-
+
case MUTE_TOGGLE:
pa_sink_set_mute(s, PA_MIXER_HARDWARE, !pa_sink_get_mute(s, PA_MIXER_HARDWARE));
}
return;
-
+
fail:
u->module->core->mainloop->io_free(u->io);
u->io = NULL;
}
#define test_bit(bit, array) (array[bit/8] & (1<<(bit%8)))
-
+
int pa__init(pa_core *c, pa_module*m) {
pa_modargs *ma = NULL;
struct userdata *u;
u->io = c->mainloop->io_new(c->mainloop, u->fd, PA_IO_EVENT_INPUT|PA_IO_EVENT_HANGUP, io_callback, u);
pa_modargs_free(ma);
-
+
return 0;
fail:
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_log("invalid file descriptor.");
goto finish;
}
-
+
io = pa_iochannel_new(c->mainloop, fd, fd);
if (!(m->userdata = pa_protocol_native_new_iochannel(c, io, m, ma))) {
finish:
if (ma)
pa_modargs_free(ma);
-
+
return r;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_sample_spec ss;
pa_channel_map map;
pa_modargs *ma = NULL;
-
+
assert(c);
assert(m);
-
+
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
pa_log("failed to parse module arguments.");
goto fail;
pa_log("invalid sample format specification or channel map.");
goto fail;
}
-
+
u = pa_xnew0(struct userdata, 1);
u->core = c;
u->module = m;
m->userdata = u;
-
+
if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) {
pa_log("failed to create sink.");
goto fail;
u->n_bytes = 0;
pa_gettimeofday(&u->start_time);
-
+
u->time_event = c->mainloop->time_new(c->mainloop, &u->start_time, time_callback, u);
u->block_size = pa_bytes_per_second(&ss) / 10;
-
+
pa_modargs_free(ma);
-
+
return 0;
fail:
if (ma)
pa_modargs_free(ma);
-
+
pa__done(c, m);
return -1;
if (!(u = m->userdata))
return;
-
+
pa_sink_disconnect(u->sink);
pa_sink_unref(u->sink);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
#define DEFAULT_FRAGSIZE 1024
static void update_usage(struct userdata *u) {
- pa_module_set_used(u->module,
+ pa_module_set_used(u->module,
(u->sink ? pa_sink_used_by(u->sink) : 0) +
(u->source ? pa_source_used_by(u->source) : 0));
}
pa_sink_unref(u->sink);
u->sink = NULL;
}
-
+
if (u->source) {
pa_source_disconnect(u->source);
pa_source_unref(u->source);
munmap(u->in_mmap, u->in_mmap_length);
u->in_mmap = NULL;
}
-
+
if (u->out_mmap && u->out_mmap != MAP_FAILED) {
munmap(u->out_mmap, u->out_mmap_length);
u->out_mmap = NULL;
}
-
+
if (u->io_event) {
u->core->mainloop->io_free(u->io_event);
u->io_event = NULL;
static void out_fill_memblocks(struct userdata *u, unsigned n) {
assert(u && u->out_memblocks);
-
+
while (n > 0) {
pa_memchunk chunk;
-
+
if (u->out_memblocks[u->out_current])
pa_memblock_unref_fixed(u->out_memblocks[u->out_current]);
-
+
chunk.memblock = u->out_memblocks[u->out_current] =
pa_memblock_new_fixed(
u->core->mempool,
assert(chunk.memblock);
chunk.length = chunk.memblock->length;
chunk.index = 0;
-
+
pa_sink_render_into_full(u->sink, &chunk);
-
+
u->out_current++;
while (u->out_current >= u->out_fragments)
u->out_current -= u->out_fragments;
-
+
n--;
}
}
assert(u && u->sink);
update_usage(u);
-
+
if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) {
pa_log("SNDCTL_DSP_GETOPTR: %s", pa_cstrerror(errno));
info.blocks += u->out_blocks_saved;
u->out_blocks_saved = 0;
-
+
if (!info.blocks)
return;
-
+
out_fill_memblocks(u, info.blocks);
}
static void in_post_memblocks(struct userdata *u, unsigned n) {
assert(u && u->in_memblocks);
-
+
while (n > 0) {
pa_memchunk chunk;
-
+
if (!u->in_memblocks[u->in_current]) {
chunk.memblock = u->in_memblocks[u->in_current] = pa_memblock_new_fixed(u->core->mempool, (uint8_t*) u->in_mmap+u->in_fragment_size*u->in_current, u->in_fragment_size, 1);
chunk.length = chunk.memblock->length;
chunk.index = 0;
-
+
pa_source_post(u->source, &chunk);
}
u->in_current++;
while (u->in_current >= u->in_fragments)
u->in_current -= u->in_fragments;
-
+
n--;
}
}
if (n > u->in_fragments)
n = u->in_fragments;
-
+
while (n > 0) {
if (u->in_memblocks[i]) {
pa_memblock_unref_fixed(u->in_memblocks[i]);
assert(u && u->source);
update_usage(u);
-
+
if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) {
pa_log("SNDCTL_DSP_GETIPTR: %s", pa_cstrerror(errno));
info.blocks += u->in_blocks_saved;
u->in_blocks_saved = 0;
-
+
if (!info.blocks)
return;
-
+
in_post_memblocks(u, info.blocks);
in_clear_memblocks(u, u->in_fragments/2);
}
n = bpos - info.ptr;
/* pa_log("n = %u, bpos = %u, ptr = %u, total=%u, fragsize = %u, n_frags = %u\n", n, bpos, (unsigned) info.ptr, total, u->out_fragment_size, u->out_fragments); */
-
+
return pa_bytes_to_usec(n, &s->sample_spec);
}
n = (u->in_fragments * u->in_fragment_size) - bpos + info.ptr;
/* pa_log("n = %u, bpos = %u, ptr = %u, total=%u, fragsize = %u, n_frags = %u\n", n, bpos, (unsigned) info.ptr, total, u->in_fragment_size, u->in_fragments); */
-
+
return pa_bytes_to_usec(n, &s->sample_spec);
}
pa_log("failed to parse module arguments.");
goto fail;
}
-
+
if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) {
pa_log("record= and playback= expect numeric arguments.");
goto fail;
if (nfrags >= 2 && frag_size >= 1)
if (pa_oss_set_fragments(u->fd, nfrags, frag_size) < 0)
goto fail;
-
+
if (pa_oss_auto_format(u->fd, &u->sample_spec) < 0)
goto fail;
if (!(u->source = pa_source_new(c, __FILE__, name, namereg_fail, &u->sample_spec, &map)))
goto fail;
-
+
u->source->userdata = u;
u->source->get_latency = source_get_latency_cb;
u->source->get_hw_volume = source_get_hw_volume;
hwdesc[0] ? ")" : ""));
pa_xfree(t);
u->source->is_hardware = 1;
-
+
u->in_memblocks = pa_xnew0(pa_memblock*, u->in_fragments);
-
+
enable_bits |= PCM_ENABLE_INPUT;
}
}
pa_xfree(name_buf);
name_buf = NULL;
-
+
if (mode != O_RDONLY) {
if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0) {
pa_log("SNDCTL_DSP_GETOSPACE: %s", pa_cstrerror(errno));
goto fail;
}
-
+
pa_log_info("output -- %u fragments of size %u.", info.fragstotal, info.fragsize);
u->out_mmap_length = (u->out_fragment_size = info.fragsize) * (u->out_fragments = info.fragstotal);
name = name_buf = pa_sprintf_malloc("oss_output.%s", pa_path_get_filename(p));
namereg_fail = 0;
}
-
+
if (!(u->sink = pa_sink_new(c, __FILE__, name, namereg_fail, &u->sample_spec, &map)))
goto fail;
hwdesc[0] ? hwdesc : "",
hwdesc[0] ? ")" : ""));
pa_xfree(t);
-
+
u->sink->is_hardware = 1;
u->out_memblocks = pa_xmalloc0(sizeof(struct memblock *)*u->out_fragments);
-
+
enable_bits |= PCM_ENABLE_OUTPUT;
}
}
pa_xfree(name_buf);
name_buf = NULL;
-
+
zero = 0;
if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &zero) < 0) {
pa_log("SNDCTL_DSP_SETTRIGGER: %s", pa_cstrerror(errno));
goto fail;
}
-
+
if (ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &enable_bits) < 0) {
pa_log("SNDCTL_DSP_SETTRIGGER: %s", pa_cstrerror(errno));
goto fail;
}
-
+
assert(u->source || u->sink);
u->io_event = c->mainloop->io_new(c->mainloop, u->fd, (u->source ? PA_IO_EVENT_INPUT : 0) | (u->sink ? PA_IO_EVENT_OUTPUT : 0), io_callback, u);
source_get_hw_volume(u->source);
if (u->sink)
sink_get_hw_volume(u->sink);
-
+
return 0;
fail:
pa_modargs_free(ma);
pa_xfree(name_buf);
-
+
return -1;
}
void pa__done(pa_core *c, pa_module*m) {
struct userdata *u;
-
+
assert(c);
assert(m);
pa_memblock_unref_fixed(u->in_memblocks[i]);
pa_xfree(u->in_memblocks);
}
-
+
pa_xfree(u);
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
#define DEFAULT_DEVICE "/dev/dsp"
static void update_usage(struct userdata *u) {
- pa_module_set_used(u->module,
+ pa_module_set_used(u->module,
(u->sink ? pa_sink_used_by(u->sink) : 0) +
(u->source ? pa_source_used_by(u->source) : 0));
}
static void clear_up(struct userdata *u) {
assert(u);
-
+
if (u->sink) {
pa_sink_disconnect(u->sink);
pa_sink_unref(u->sink);
u->sink = NULL;
}
-
+
if (u->source) {
pa_source_disconnect(u->source);
pa_source_unref(u->source);
ssize_t r;
size_t l;
int loop = 0;
-
+
assert(u);
if (!u->sink || !pa_iochannel_is_writable(u->io))
update_usage(u);
l = u->out_fragment_size;
-
+
if (u->use_getospace) {
audio_buf_info info;
-
+
if (ioctl(u->fd, SNDCTL_DSP_GETOSPACE, &info) < 0)
u->use_getospace = 0;
else {
do {
memchunk = &u->memchunk;
-
+
if (!memchunk->length)
if (pa_sink_render(u->sink, l, memchunk) < 0)
memchunk = &u->silence;
-
+
assert(memchunk->memblock);
assert(memchunk->memblock->data);
assert(memchunk->length);
-
+
if ((r = pa_iochannel_write(u->io, (uint8_t*) memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) {
pa_log("write() failed: %s", pa_cstrerror(errno));
pa_module_unload_request(u->module);
break;
}
-
+
if (memchunk == &u->silence)
assert(r % u->sample_size == 0);
else {
u->memchunk.index += r;
u->memchunk.length -= r;
-
+
if (u->memchunk.length <= 0) {
pa_memblock_unref(u->memchunk.memblock);
u->memchunk.memblock = NULL;
size_t l;
int loop = 0;
assert(u);
-
+
if (!u->source || !pa_iochannel_is_readable(u->io) || !pa_idxset_size(u->source->outputs))
return;
if (u->use_getispace) {
audio_buf_info info;
-
+
if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0)
u->use_getispace = 0;
else {
}
}
}
-
+
do {
memchunk.memblock = pa_memblock_new(u->core->mempool, l);
assert(memchunk.memblock);
}
break;
}
-
+
assert(r <= (ssize_t) memchunk.memblock->length);
memchunk.length = memchunk.memblock->length = r;
memchunk.index = 0;
-
+
pa_source_post(u->source, &memchunk);
pa_memblock_unref(memchunk.memblock);
if (!u->use_getispace)
return 0;
-
+
if (ioctl(u->fd, SNDCTL_DSP_GETISPACE, &info) < 0) {
u->use_getispace = 0;
return 0;
}
-
+
if (info.bytes <= 0)
return 0;
const char *name;
char *name_buf = NULL;
int namereg_fail;
-
+
assert(c);
assert(m);
pa_log("failed to parse module arguments.");
goto fail;
}
-
+
if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) {
pa_log("record= and playback= expect numeric argument.");
goto fail;
pa_log("failed to parse sample specification or channel map");
goto fail;
}
-
+
/* Fix latency to 100ms */
nfrags = 12;
frag_size = pa_bytes_per_second(&ss)/128;
-
+
if (pa_modargs_get_value_s32(ma, "fragments", &nfrags) < 0 || pa_modargs_get_value_s32(ma, "fragment_size", &frag_size) < 0) {
pa_log("failed to parse fragments arguments");
goto fail;
pa_log_info("hardware name is '%s'.", hwdesc);
else
hwdesc[0] = 0;
-
+
pa_log_info("device opened in %s mode.", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR"));
if (nfrags >= 2 && frag_size >= 1)
- if (pa_oss_set_fragments(fd, nfrags, frag_size) < 0)
- goto fail;
+ if (pa_oss_set_fragments(fd, nfrags, frag_size) < 0)
+ goto fail;
if (pa_oss_auto_format(fd, &ss) < 0)
goto fail;
u = pa_xmalloc(sizeof(struct userdata));
u->core = c;
u->use_getospace = u->use_getispace = 0;
-
+
if (ioctl(fd, SNDCTL_DSP_GETISPACE, &info) >= 0) {
pa_log_info("input -- %u fragments of size %u.", info.fragstotal, info.fragsize);
in_frag_size = info.fragsize;
name = name_buf = pa_sprintf_malloc("oss_input.%s", pa_path_get_filename(p));
namereg_fail = 0;
}
-
+
if (!(u->source = pa_source_new(c, __FILE__, name, namereg_fail, &ss, &map)))
goto fail;
name = name_buf = pa_sprintf_malloc("oss_output.%s", pa_path_get_filename(p));
namereg_fail = 0;
}
-
+
if (!(u->sink = pa_sink_new(c, __FILE__, name, namereg_fail, &ss, &map)))
goto fail;
pa_xfree(name_buf);
name_buf = NULL;
-
+
assert(u->source || u->sink);
u->io = pa_iochannel_new(c->mainloop, u->source ? fd : -1, u->sink ? fd : -1);
pa_modargs_free(ma);
pa_xfree(name_buf);
-
+
return -1;
}
void pa__done(pa_core *c, pa_module*m) {
struct userdata *u;
-
+
assert(c);
assert(m);
return;
clear_up(u);
-
+
if (u->memchunk.memblock)
pa_memblock_unref(u->memchunk.memblock);
if (u->silence.memblock)
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_core *core;
char *filename;
-
+
pa_sink *sink;
pa_iochannel *io;
pa_defer_event *defer_event;
assert(u);
u->core->mainloop->defer_enable(u->defer_event, 0);
-
+
if (!pa_iochannel_is_writable(u->io))
return;
pa_module_set_used(u->module, pa_sink_used_by(u->sink));
-
+
if (!u->memchunk.length)
if (pa_sink_render(u->sink, PIPE_BUF, &u->memchunk) < 0)
return;
assert(u->memchunk.memblock && u->memchunk.length);
-
+
if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) {
pa_log("write(): %s", pa_cstrerror(errno));
return;
u->memchunk.index += r;
u->memchunk.length -= r;
-
+
if (u->memchunk.length <= 0) {
pa_memblock_unref(u->memchunk.memblock);
u->memchunk.memblock = NULL;
pa_channel_map map;
pa_modargs *ma = NULL;
char *t;
-
+
assert(c && m);
-
+
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
pa_log("failed to parse module arguments");
goto fail;
pa_log("invalid sample format specification");
goto fail;
}
-
+
mkfifo(p = pa_modargs_get_value(ma, "file", DEFAULT_FIFO_NAME), 0777);
if ((fd = open(p, O_RDWR)) < 0) {
}
pa_fd_set_cloexec(fd, 1);
-
+
if (fstat(fd, &st) < 0) {
pa_log("fstat('%s'): %s", p, pa_cstrerror(errno));
goto fail;
u->core = c;
u->module = m;
m->userdata = u;
-
+
if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, &map))) {
pa_log("failed to create sink.");
goto fail;
c->mainloop->defer_enable(u->defer_event, 0);
pa_modargs_free(ma);
-
+
return 0;
fail:
if (ma)
pa_modargs_free(ma);
-
+
if (fd >= 0)
close(fd);
if (!(u = m->userdata))
return;
-
+
if (u->memchunk.memblock)
pa_memblock_unref(u->memchunk.memblock);
-
+
pa_sink_disconnect(u->sink);
pa_sink_unref(u->sink);
pa_iochannel_free(u->io);
assert(u->filename);
unlink(u->filename);
pa_xfree(u->filename);
-
+
pa_xfree(u);
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_core *core;
char *filename;
-
+
pa_source *source;
pa_iochannel *io;
pa_module *module;
pa_channel_map map;
pa_modargs *ma = NULL;
char *t;
-
+
assert(c && m);
-
+
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
pa_log("failed to parse module arguments");
goto fail;
pa_log("invalid sample format specification or channel map");
goto fail;
}
-
+
mkfifo(p = pa_modargs_get_value(ma, "file", DEFAULT_FIFO_NAME), 0777);
if ((fd = open(p, O_RDWR)) < 0) {
}
pa_fd_set_cloexec(fd, 1);
-
+
if (fstat(fd, &st) < 0) {
pa_log("fstat('%s'): %s", p, pa_cstrerror(errno));
goto fail;
u->filename = pa_xstrdup(p);
u->core = c;
-
+
if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, &map))) {
pa_log("failed to create source.");
goto fail;
u->chunk.memblock = NULL;
u->chunk.index = u->chunk.length = 0;
-
+
u->module = m;
m->userdata = u;
pa_modargs_free(ma);
-
+
return 0;
fail:
if (ma)
pa_modargs_free(ma);
-
+
if (fd >= 0)
close(fd);
if (!(u = m->userdata))
return;
-
+
if (u->chunk.memblock)
pa_memblock_unref(u->chunk.memblock);
-
+
pa_source_disconnect(u->source);
pa_source_unref(u->source);
pa_iochannel_free(u->io);
assert(u->filename);
unlink(u->filename);
pa_xfree(u->filename);
-
+
pa_xfree(u);
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
"record=<enable record?> "
SOCKET_USAGE)
#elif defined(USE_PROTOCOL_CLI)
- #include <pulsecore/protocol-cli.h>
+ #include <pulsecore/protocol-cli.h>
#define protocol_new pa_protocol_cli_new
#define protocol_free pa_protocol_cli_free
#define TCPWRAP_SERVICE "pulseaudio-cli"
#define IPV4_PORT 4712
#define UNIX_SOCKET "cli"
- #define MODULE_ARGUMENTS
+ #define MODULE_ARGUMENTS
#ifdef USE_TCP_SOCKETS
#include "module-cli-protocol-tcp-symdef.h"
#else
#define TCPWRAP_SERVICE "pulseaudio-http"
#define IPV4_PORT 4714
#define UNIX_SOCKET "http"
- #define MODULE_ARGUMENTS
+ #define MODULE_ARGUMENTS
#ifdef USE_TCP_SOCKETS
#include "module-http-protocol-tcp-symdef.h"
#else
#endif
#if defined(HAVE_CREDS) && !defined(USE_TCP_SOCKETS)
- #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-group", "auth-group-enable",
+ #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-group", "auth-group-enable",
#define AUTH_USAGE "auth-group=<system group to allow access> auth-group-enable=<enable auth by UNIX group?> "
#elif defined(USE_TCP_SOCKETS)
- #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-ip-acl",
+ #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-ip-acl",
#define AUTH_USAGE "auth-ip-acl=<IP address ACL to allow access> "
#else
#define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON
#define AUTH_USAGE
#endif
-
+
PA_MODULE_DESCRIPTION("Native protocol "SOCKET_DESCRIPTION)
PA_MODULE_USAGE("auth-anonymous=<don't check for cookies?> "
"cookie=<path to cookie file> "
#endif
#if defined(USE_TCP_SOCKETS)
- #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-ip-acl",
+ #define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON "auth-ip-acl",
#define AUTH_USAGE "auth-ip-acl=<IP address ACL to allow access> "
#else
#define MODULE_ARGUMENTS MODULE_ARGUMENTS_COMMON
AUTH_USAGE
SOCKET_USAGE)
#else
- #error "Broken build system"
+ #error "Broken build system"
#endif
PA_MODULE_AUTHOR("Lennart Poettering")
/* This socket doesn't reside in our own runtime dir but in
* /tmp/.esd/, hence we have to create the dir first */
-
+
if (pa_make_secure_parent_dir(u->socket_path, c->is_system_instance ? 0755 : 0700, (uid_t)-1, (gid_t)-1) < 0) {
pa_log("Failed to create socket directory: %s\n", pa_cstrerror(errno));
goto fail;
}
#endif
-
+
if ((r = pa_unix_socket_remove_stale(tmp)) < 0) {
pa_log("Failed to remove stale UNIX socket '%s': %s", tmp, pa_cstrerror(errno));
goto fail;
}
-
+
if (r)
pa_log("Removed stale UNIX socket '%s'.", tmp);
-
+
if (!(s = pa_socket_server_new_unix(c->mainloop, tmp)))
goto fail;
void pa__done(pa_core *c, pa_module*m) {
struct userdata *u;
-
+
assert(c);
assert(m);
pa_xfree(p);
}
#endif
-
-
+
+
pa_xfree(u->socket_path);
#endif
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
static pa_hook_result_t sink_hook_callback(pa_core *c, pa_sink *sink, void* userdata) {
pa_sink_input *i;
pa_sink *target;
-
+
assert(c);
assert(sink);
pa_log_debug("No sink inputs to move away.");
return PA_HOOK_OK;
}
-
+
if (!(target = pa_namereg_get(c, NULL, PA_NAMEREG_SINK, 0))) {
pa_log_info("No evacuation sink found.");
return PA_HOOK_OK;
pa_log_info("Sucessfully moved sink input %u \"%s\" to %s.", i->index, i->name, target->name);
}
-
+
return PA_HOOK_OK;
}
static pa_hook_result_t source_hook_callback(pa_core *c, pa_source *source, void* userdata) {
pa_source_output *o;
pa_source *target;
-
+
assert(c);
assert(source);
pa_log_debug("No source outputs to move away.");
return PA_HOOK_OK;
}
-
+
if (!(target = pa_namereg_get(c, NULL, PA_NAMEREG_SOURCE, 0))) {
pa_log_info("No evacuation source found.");
return PA_HOOK_OK;
pa_log_info("Sucessfully moved source output %u \"%s\" to %s.", o->index, o->name, target->name);
}
-
+
return PA_HOOK_OK;
}
int pa__init(pa_core *c, pa_module*m) {
pa_modargs *ma = NULL;
struct userdata *u;
-
+
assert(c);
assert(m);
void pa__done(pa_core *c, pa_module*m) {
struct userdata *u;
-
+
assert(c);
assert(m);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
size_t i;
l /= sizeof(float);
-
+
for (i = 0; i < l; i++)
f[i] = (float) sin((double) i/l*M_PI*2*freq)/2;
}
pa_log("Failed to parse module arguments");
goto fail;
}
-
+
m->userdata = u = pa_xmalloc(sizeof(struct userdata));
u->core = c;
u->module = m;
pa_log("Invalid frequency specification");
goto fail;
}
-
+
u->memblock = pa_memblock_new(c->mempool, pa_bytes_per_second(&ss));
calc_sine(u->memblock->data, u->memblock->length, frequency);
u->sink_input->userdata = u;
u->peek_index = 0;
-
+
pa_modargs_free(ma);
return 0;
-
+
fail:
if (ma)
pa_modargs_free(ma);
pa_sink_input_disconnect(u->sink_input);
pa_sink_input_unref(u->sink_input);
}
-
+
if (u->memblock)
pa_memblock_unref(u->memblock);
pa_xfree(u);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
int err;
size_t len;
ssize_t r;
-
+
assert(u);
/* We cannot check pa_iochannel_is_writable() because of our buffer hack */
}
u->sink_underflow = 0;
-
+
assert(u->memchunk.memblock);
assert(u->memchunk.memblock->data);
assert(u->memchunk.length);
}
assert(r % u->frame_size == 0);
-
+
u->memchunk.index += r;
u->memchunk.length -= r;
-
+
if (u->memchunk.length <= 0) {
pa_memblock_unref(u->memchunk.memblock);
u->memchunk.memblock = NULL;
size_t l;
ssize_t r;
assert(u);
-
+
if (!u->source || !pa_iochannel_is_readable(u->io))
return;
pa_log("read() failed: %s", pa_cstrerror(errno));
return;
}
-
+
assert(r <= (ssize_t) memchunk.memblock->length);
memchunk.length = memchunk.memblock->length = r;
memchunk.index = 0;
-
+
pa_source_post(u->source, &memchunk);
pa_memblock_unref(memchunk.memblock);
static void sig_callback(pa_mainloop_api *api, pa_signal_event*e, int sig, void *userdata) {
struct userdata *u = userdata;
pa_cvolume old_vol;
-
+
assert(u);
if (u->sink) {
pa_log("failed to parse module arguments.");
goto fail;
}
-
+
if (pa_modargs_get_value_boolean(ma, "record", &record) < 0 || pa_modargs_get_value_boolean(ma, "playback", &playback) < 0) {
pa_log("record= and playback= expect numeric argument.");
goto fail;
mode = (playback&&record) ? O_RDWR : (playback ? O_WRONLY : (record ? O_RDONLY : 0));
- buffer_size = 16384;
+ buffer_size = 16384;
if (pa_modargs_get_value_s32(ma, "buffer_size", &buffer_size) < 0) {
pa_log("failed to parse buffer size argument");
goto fail;
pa_log("failed to parse sample specification");
goto fail;
}
-
+
if ((fd = open(p = pa_modargs_get_value(ma, "device", DEFAULT_DEVICE), mode | O_NONBLOCK)) < 0)
goto fail;
if (ma)
pa_modargs_free(ma);
-
+
return -1;
}
c->mainloop->time_free(u->timer);
ioctl(u->fd, I_SETSIG, 0);
pa_signal_free(u->sig);
-
+
if (u->memchunk.memblock)
pa_memblock_unref(u->memchunk.memblock);
pa_sink_disconnect(u->sink);
pa_sink_unref(u->sink);
}
-
+
if (u->source) {
pa_source_disconnect(u->source);
pa_source_unref(u->source);
}
-
+
pa_iochannel_free(u->io);
pa_xfree(u);
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = {
#ifdef TUNNEL_SINK
[PA_COMMAND_REQUEST] = command_request,
-#endif
+#endif
[PA_COMMAND_PLAYBACK_STREAM_KILLED] = command_stream_killed,
[PA_COMMAND_RECORD_STREAM_KILLED] = command_stream_killed,
- [PA_COMMAND_SUBSCRIBE_EVENT] = command_subscribe_event,
+ [PA_COMMAND_SUBSCRIBE_EVENT] = command_subscribe_event,
};
struct userdata {
char *source_name;
pa_source *source;
#endif
-
+
pa_module *module;
pa_core *core;
uint32_t ctag;
uint32_t device_index;
uint32_t channel;
-
+
pa_usec_t host_latency;
pa_time_event *time_event;
static void close_stuff(struct userdata *u) {
assert(u);
-
+
if (u->pstream) {
pa_pstream_close(u->pstream);
pa_pstream_unref(u->pstream);
while (u->requested_bytes > 0) {
pa_memchunk chunk;
if (pa_sink_render(u->sink, u->requested_bytes, &chunk) < 0) {
-
- if (u->requested_bytes >= DEFAULT_TLENGTH-DEFAULT_PREBUF)
+
+ if (u->requested_bytes >= DEFAULT_TLENGTH-DEFAULT_PREBUF)
send_prebuf_request(u);
-
+
return;
}
die(u);
return;
}
-
+
u->requested_bytes += bytes;
send_bytes(u);
}
die(u);
return;
}
-
+
if (pa_tagstruct_get_usec(t, &sink_usec) < 0 ||
pa_tagstruct_get_usec(t, &source_usec) < 0 ||
pa_tagstruct_get_boolean(t, &playing) < 0 ||
pa_gettimeofday(&now);
/* FIXME! This could use some serious love. */
-
+
if (pa_timeval_cmp(&local, &remote) < 0 && pa_timeval_cmp(&remote, &now)) {
/* local and remote seem to have synchronized clocks */
#ifdef TUNNEL_SINK
transport_usec = pa_timeval_diff(&remote, &local);
#else
transport_usec = pa_timeval_diff(&now, &remote);
-#endif
+#endif
} else
transport_usec = pa_timeval_diff(&now, &local)/2;
assert(u);
t = pa_tagstruct_new(NULL, 0);
-#ifdef TUNNEL_SINK
+#ifdef TUNNEL_SINK
pa_tagstruct_putu32(t, PA_COMMAND_GET_PLAYBACK_LATENCY);
#else
pa_tagstruct_putu32(t, PA_COMMAND_GET_RECORD_LATENCY);
pa_gettimeofday(&now);
pa_tagstruct_put_timeval(t, &now);
-
+
pa_pstream_send_tagstruct(u->pstream, t);
pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_latency_callback, u, NULL);
}
assert(m && e && u);
request_latency(u);
-
+
pa_gettimeofday(&ntv);
ntv.tv_sec += LATENCY_INTERVAL;
m->time_restart(e, &ntv);
if (pa_tagstruct_getu32(t, &u->channel) < 0 ||
pa_tagstruct_getu32(t, &u->device_index) < 0
-#ifdef TUNNEL_SINK
+#ifdef TUNNEL_SINK
|| pa_tagstruct_getu32(t, &u->requested_bytes) < 0
-#endif
+#endif
)
goto parse_error;
if (u->version >= 9) {
#ifdef TUNNEL_SINK
uint32_t maxlength, tlength, prebuf, minreq;
-
+
if (pa_tagstruct_getu32(t, &maxlength) < 0 ||
pa_tagstruct_getu32(t, &tlength) < 0 ||
pa_tagstruct_getu32(t, &prebuf) < 0 ||
goto parse_error;
#else
uint32_t maxlength, fragsize;
-
+
if (pa_tagstruct_getu32(t, &maxlength) < 0 ||
- pa_tagstruct_getu32(t, &fragsize) < 0)
+ pa_tagstruct_getu32(t, &fragsize) < 0)
goto parse_error;
#endif
}
-
+
if (!pa_tagstruct_eof(t))
goto parse_error;
#endif
return;
-
+
parse_error:
pa_log("invalid reply. (create stream)");
die(u);
pa_get_user_name(un, sizeof(un)),
u->source->name);
#endif
-
+
reply = pa_tagstruct_new(NULL, 0);
pa_tagstruct_putu32(reply, PA_COMMAND_SET_CLIENT_NAME);
pa_tagstruct_putu32(reply, tag = u->ctag++);
/* We ignore the server's reply here */
reply = pa_tagstruct_new(NULL, 0);
-#ifdef TUNNEL_SINK
+#ifdef TUNNEL_SINK
pa_tagstruct_putu32(reply, PA_COMMAND_CREATE_PLAYBACK_STREAM);
pa_tagstruct_putu32(reply, tag = u->ctag++);
pa_tagstruct_puts(reply, name);
pa_tagstruct_put_boolean(reply, 0);
pa_tagstruct_putu32(reply, DEFAULT_FRAGSIZE);
#endif
-
+
pa_pstream_send_tagstruct(u->pstream, reply);
pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, create_stream_callback, u, NULL);
}
die(u);
return;
}
-
+
pa_source_post(u->source, chunk);
}
#endif
pa_socket_client_unref(u->client);
u->client = NULL;
-
+
if (!io) {
pa_log("connection failed.");
pa_module_unload_request(u->module);
#ifndef TUNNEL_SINK
pa_pstream_set_recieve_memblock_callback(u->pstream, pstream_memblock_callback, u);
#endif
-
+
t = pa_tagstruct_new(NULL, 0);
pa_tagstruct_putu32(t, PA_COMMAND_AUTH);
pa_tagstruct_putu32(t, tag = u->ctag++);
pa_tagstruct_put_arbitrary(t, u->auth_cookie, sizeof(u->auth_cookie));
pa_pstream_send_tagstruct(u->pstream, t);
pa_pdispatch_register_reply(u->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, u, NULL);
-
+
}
#ifdef TUNNEL_SINK
assert(u);
u->auth_cookie_in_property = 0;
-
+
if (!fn && pa_authkey_prop_get(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) {
pa_log_debug("using already loaded auth cookie.");
pa_authkey_prop_ref(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME);
u->auth_cookie_in_property = 1;
return 0;
}
-
+
if (!fn)
fn = PA_NATIVE_COOKIE_FILE;
return -1;
pa_log_debug("loading cookie from disk.");
-
+
if (pa_authkey_prop_put(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0)
u->auth_cookie_in_property = 1;
pa_sample_spec ss;
pa_channel_map map;
char *t, *dn = NULL;
-
+
assert(c && m);
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
u->host_latency = 0;
u->auth_cookie_in_property = 0;
u->time_event = NULL;
-
+
if (load_key(u, pa_modargs_get_value(ma, "cookie", NULL)) < 0)
goto fail;
-
+
if (!(u->server_name = pa_xstrdup(pa_modargs_get_value(ma, "server", NULL)))) {
pa_log("no server specified.");
goto fail;
pa_log("failed to connect to server '%s'", u->server_name);
goto fail;
}
-
+
if (!u->client)
goto fail;
pa_source_set_owner(u->source, m);
#endif
-
+
pa_xfree(dn);
u->time_event = NULL;
pa_modargs_free(ma);
return 0;
-
+
fail:
pa__done(c, m);
pa_modargs_free(ma);
pa_xfree(dn);
-
+
return -1;
}
if (u->auth_cookie_in_property)
pa_authkey_prop_unref(c, PA_NATIVE_COOKIE_PROPERTY_NAME);
-
+
#ifdef TUNNEL_SINK
pa_xfree(u->sink_name);
#else
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
char *p;
long k;
unsigned i;
-
+
assert(s);
assert(v);
k = strtol(s, &p, 0);
if (k <= 0 || k > PA_CHANNELS_MAX)
return NULL;
-
+
v->channels = (unsigned) k;
for (i = 0; i < v->channels; i++) {
if (k < PA_VOLUME_MUTED)
return NULL;
-
+
v->values[i] = (pa_volume_t) k;
}
ret = 0;
} else
pa_log("failed to open file '%s': %s", u->table_file, pa_cstrerror(errno));
-
+
goto finish;
}
pa_lock_fd(fileno(f), 1);
-
+
while (!feof(f)) {
struct rule *rule;
pa_cvolume v;
int v_is_set;
-
+
if (!fgets(ln, sizeof(buf_name), f))
break;
n++;
-
+
pa_strip_nl(ln);
if (ln[0] == '#')
v_is_set = 0;
ln = buf_name;
-
+
if (pa_hashmap_get(u->hashmap, buf_name)) {
pa_log("double entry in %s:%u, ignoring", u->table_file, n);
continue;
}
-
+
rule = pa_xnew(struct rule, 1);
rule->name = pa_xstrdup(buf_name);
if ((rule->volume_is_set = v_is_set))
}
ret = 0;
-
+
finish:
if (f) {
pa_lock_fd(fileno(f), 0);
int ret = -1;
void *state = NULL;
struct rule *rule;
-
+
f = u->table_file ?
fopen(u->table_file, "w") :
pa_open_config_file(NULL, DEFAULT_VOLUME_TABLE_FILE, NULL, &u->table_file, "w");
while ((rule = pa_hashmap_iterate(u->hashmap, &state, NULL))) {
unsigned i;
-
+
fprintf(f, "%s\n", rule->name);
if (rule->volume_is_set) {
for (i = 0; i < rule->volume.channels; i++)
fprintf(f, " %u", rule->volume.values[i]);
}
-
+
fprintf(f, "\n%s\n%s\n",
rule->sink ? rule->sink : "",
rule->source ? rule->source : "");
}
-
+
ret = 0;
-
+
finish:
if (f) {
pa_lock_fd(fileno(f), 0);
static char* client_name(pa_client *c) {
char *t, *e;
-
+
if (!c->name || !c->driver)
return NULL;
* sessions of the same application, which is something we
* explicitly don't want. Besides other stuff this makes xmms
* with esound work properly for us. */
-
+
if (*k == ')' && *(k+1) == 0)
*e = 0;
}
-
+
return t;
}
pa_source_output *so = NULL;
struct rule *r;
char *name;
-
+
assert(c);
assert(u);
if ((t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK_INPUT) {
if (!(si = pa_idxset_get_by_index(c->sink_inputs, idx)))
return;
-
+
if (!si->client || !(name = client_name(si->client)))
return;
} else {
if (!(so = pa_idxset_get_by_index(c->source_outputs, idx)))
return;
-
+
if (!so->client || !(name = client_name(so->client)))
return;
}
u->modified = 1;
}
}
-
+
} else {
pa_log_info("Creating new entry for <%s>", name);
r->sink = NULL;
r->source = pa_xstrdup(so->source->name);
}
-
+
pa_hashmap_put(u->hashmap, r->name, r);
u->modified = 1;
}
int pa__init(pa_core *c, pa_module*m) {
pa_modargs *ma = NULL;
struct userdata *u;
-
+
assert(c);
assert(m);
u->subscription = NULL;
u->table_file = pa_xstrdup(pa_modargs_get_value(ma, "table", NULL));
u->modified = 0;
-
+
m->userdata = u;
-
+
if (load_rules(u) < 0)
goto fail;
if (ma)
pa_modargs_free(ma);
-
+
return -1;
}
void pa__done(pa_core *c, pa_module*m) {
struct userdata* u;
-
+
assert(c);
assert(m);
if (u->modified)
save_rules(u);
-
+
pa_hashmap_free(u->hashmap, free_func, NULL);
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_log_error(__FILE__ ": ERROR: Unable to write waveOut block: %d",
res);
}
-
+
u->written_bytes += hdr->dwBufferLength;
EnterCriticalSection(&u->crit);
pa_log_error(__FILE__ ": ERROR: Unable to add waveIn block: %d",
res);
}
-
+
free_frags--;
u->cur_ihdr++;
u->cur_ihdr %= u->fragments;
u->ohdrs[i].lpData = pa_xmalloc(u->fragment_size);
assert(u->ohdrs);
}
-
+
u->module = m;
m->userdata = u;
if (ma)
pa_modargs_free(ma);
-
+
return -1;
}
if (!(u = m->userdata))
return;
-
+
if (u->event)
c->mainloop->time_free(u->event);
pa_sink_disconnect(u->sink);
pa_sink_unref(u->sink);
}
-
+
if (u->source) {
pa_source_disconnect(u->source);
pa_source_unref(u->source);
}
-
+
if (u->hwi != INVALID_HANDLE_VALUE) {
waveInReset(u->hwi);
waveInClose(u->hwi);
pa_xfree(u->ohdrs);
DeleteCriticalSection(&u->crit);
-
+
pa_xfree(u);
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_log("failed to parse module arguments");
goto fail;
}
-
+
m->userdata = u = pa_xmalloc(sizeof(struct userdata));
u->core = c;
u->scache_item = pa_xstrdup(pa_modargs_get_value(ma, "sample", "x11-bell"));
u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));
u->x11_client = NULL;
- if (!(u->x11_wrapper = pa_x11_wrapper_get(c, pa_modargs_get_value(ma, "display", NULL))))
+ if (!(u->x11_wrapper = pa_x11_wrapper_get(c, pa_modargs_get_value(ma, "display", NULL))))
goto fail;
major = XkbMajorVersion;
minor = XkbMinorVersion;
-
+
if (!XkbLibraryVersion(&major, &minor)) {
pa_log("XkbLibraryVersion() failed");
goto fail;
XkbChangeEnabledControls(pa_x11_wrapper_get_display(u->x11_wrapper), XkbUseCoreKbd, XkbAudibleBellMask, 0);
u->x11_client = pa_x11_client_new(u->x11_wrapper, x11_event_callback, u);
-
+
pa_modargs_free(ma);
-
+
return 0;
-
+
fail:
if (ma)
pa_modargs_free(ma);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
assert(u);
u->auth_cookie_in_property = 0;
-
+
if (!fn && pa_authkey_prop_get(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0) {
pa_log_debug("using already loaded auth cookie.");
pa_authkey_prop_ref(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME);
u->auth_cookie_in_property = 1;
return 0;
}
-
+
if (!fn)
fn = PA_NATIVE_COOKIE_FILE;
return -1;
pa_log_debug("loading cookie from disk.");
-
+
if (pa_authkey_prop_put(u->core, PA_NATIVE_COOKIE_PROPERTY_NAME, u->auth_cookie, sizeof(u->auth_cookie)) >= 0)
u->auth_cookie_in_property = 1;
if (load_key(u, pa_modargs_get_value(ma, "cookie", NULL)) < 0)
goto fail;
- if (!(u->x11_wrapper = pa_x11_wrapper_get(c, pa_modargs_get_value(ma, "display", NULL))))
+ if (!(u->x11_wrapper = pa_x11_wrapper_get(c, pa_modargs_get_value(ma, "display", NULL))))
goto fail;
if (!(l = pa_property_get(c, PA_NATIVE_SERVER_PROPERTY_NAME)))
s = pa_strlist_tostring(l);
pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SERVER", s);
pa_xfree(s);
-
+
if (!pa_get_fqdn(hn, sizeof(hn)) || !pa_get_user_name(un, sizeof(un)))
goto fail;
-
+
u->id = pa_sprintf_malloc("%s@%s/%u", un, hn, (unsigned) getpid());
pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_ID", u->id);
pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_SINK", t);
pa_x11_set_prop(pa_x11_wrapper_get_display(u->x11_wrapper), "PULSE_COOKIE", pa_hexstr(u->auth_cookie, sizeof(u->auth_cookie), hx, sizeof(hx)));
-
+
pa_modargs_free(ma);
return 0;
-
+
fail:
if (ma)
pa_modargs_free(ma);
if (!(u = m->userdata))
return;
-
+
if (u->x11_wrapper) {
char t[256];
XSync(pa_x11_wrapper_get_display(u->x11_wrapper), False);
}
}
-
+
if (u->x11_wrapper)
pa_x11_wrapper_unref(u->x11_wrapper);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
if (!u->client || avahi_client_get_state(u->client) != AVAHI_CLIENT_S_RUNNING)
return 0;
-
+
if ((s->published == PUBLISHED_REAL && s->loaded.valid) ||
(s->published == PUBLISHED_AUTOLOAD && s->autoload.valid && !s->loaded.valid))
return 0;
if (s->published != UNPUBLISHED) {
avahi_entry_group_reset(s->entry_group);
s->published = UNPUBLISHED;
- }
-
+ }
+
if (s->loaded.valid || s->autoload.valid) {
pa_namereg_type_t type;
goto finish;
}
}
-
+
txt = avahi_string_list_add_pair(txt, "device", s->name);
txt = txt_record_server_data(u->core, txt);
-
+
if (s->loaded.valid) {
char *description;
pa_sample_spec ss;
-
+
get_service_data(u, s, &ss, &description);
-
+
txt = avahi_string_list_add_printf(txt, "rate=%u", ss.rate);
txt = avahi_string_list_add_printf(txt, "channels=%u", ss.channels);
txt = avahi_string_list_add_pair(txt, "format", pa_sample_format_to_string(ss.format));
if (description)
txt = avahi_string_list_add_pair(txt, "description", description);
-
+
type = s->loaded.type;
} else if (s->autoload.valid)
type = s->autoload.type;
-
+
if (avahi_entry_group_add_service_strlst(
s->entry_group,
AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
NULL,
u->port,
txt) < 0) {
-
+
pa_log("avahi_entry_group_add_service_strlst(): %s", avahi_strerror(avahi_client_errno(u->client)));
goto finish;
}
-
+
if (avahi_entry_group_commit(s->entry_group) < 0) {
pa_log("avahi_entry_group_commit(): %s", avahi_strerror(avahi_client_errno(u->client)));
goto finish;
}
-
+
if (s->loaded.valid)
s->published = PUBLISHED_REAL;
else if (s->autoload.valid)
s->published = PUBLISHED_AUTOLOAD;
}
-
+
r = 0;
-
+
finish:
if (s->published == UNPUBLISHED) {
if (s->entry_group)
avahi_entry_group_free(s->entry_group);
-
+
pa_hashmap_remove(u->services, s->name);
pa_xfree(s->name);
pa_xfree(s->service_name);
if (txt)
avahi_string_list_free(txt);
-
+
return r;
}
static struct service *get_service(struct userdata *u, const char *name, const char *description) {
struct service *s;
char hn[64];
-
+
if ((s = pa_hashmap_get(u->services, name)))
return s;
-
+
s = pa_xnew(struct service, 1);
s->userdata = u;
s->entry_group = NULL;
static int publish_source(struct userdata *u, pa_source *s) {
struct service *svc;
int ret;
-
+
assert(u && s);
svc = get_service(u, s->name, s->description);
svc->loaded.index = s->index;
pa_dynarray_put(u->source_dynarray, s->index, svc);
-
+
if ((ret = publish_service(u, svc)) < 0)
return ret;
static int publish_autoload(struct userdata *u, pa_autoload_entry *s) {
struct service *svc;
int ret;
-
+
assert(u && s);
svc = get_service(u, s->name, NULL);
if ((ret = publish_service(u, svc)) < 0)
return ret;
-
+
pa_dynarray_put(u->autoload_dynarray, s->index, svc);
return ret;
}
svc->loaded.valid = 0;
pa_dynarray_put(u->sink_dynarray, idx, NULL);
-
+
return publish_service(u, svc);
}
static int remove_source(struct userdata *u, uint32_t idx) {
struct service *svc;
assert(u && idx != PA_INVALID_INDEX);
-
+
if (!(svc = pa_dynarray_get(u->source_dynarray, idx)))
return 0;
static int remove_autoload(struct userdata *u, uint32_t idx) {
struct service *svc;
assert(u && idx != PA_INVALID_INDEX);
-
+
if (!(svc = pa_dynarray_get(u->autoload_dynarray, idx)))
return 0;
if (remove_sink(u, idx) < 0)
goto fail;
}
-
+
break;
case PA_SUBSCRIPTION_EVENT_SOURCE:
if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) {
pa_source *source;
-
+
if ((source = pa_idxset_get_by_index(c->sources, idx))) {
if (publish_source(u, source) < 0)
goto fail;
if (remove_source(u, idx) < 0)
goto fail;
}
-
+
break;
case PA_SUBSCRIPTION_EVENT_AUTOLOAD:
if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW) {
pa_autoload_entry *autoload;
-
+
if ((autoload = pa_idxset_get_by_index(c->autoload_idxset, idx))) {
if (publish_autoload(u, autoload) < 0)
goto fail;
if (remove_autoload(u, idx) < 0)
goto fail;
}
-
+
break;
}
static int publish_main_service(struct userdata *u) {
AvahiStringList *txt = NULL;
int r = -1;
-
+
if (!u->main_entry_group) {
if (!(u->main_entry_group = avahi_entry_group_new(u->client, main_entry_group_callback, u))) {
pa_log("avahi_entry_group_new() failed: %s", avahi_strerror(avahi_client_errno(u->client)));
}
} else
avahi_entry_group_reset(u->main_entry_group);
-
+
txt = txt_record_server_data(u->core, NULL);
if (avahi_entry_group_add_service_strlst(
NULL,
u->port,
txt) < 0) {
-
+
pa_log("avahi_entry_group_add_service_strlst() failed: %s", avahi_strerror(avahi_client_errno(u->client)));
goto fail;
}
-
+
if (avahi_entry_group_commit(u->main_entry_group) < 0) {
pa_log("avahi_entry_group_commit() failed: %s", avahi_strerror(avahi_client_errno(u->client)));
goto fail;
}
r = 0;
-
+
fail:
avahi_string_list_free(txt);
pa_autoload_entry *autoload;
int r = -1;
uint32_t idx;
-
+
assert(u);
pa_log_debug("Publishing services in Zeroconf");
if (publish_main_service(u) < 0)
goto fail;
-
+
r = 0;
-
+
fail:
return r;
}
static void unpublish_all_services(struct userdata *u, int rem) {
void *state = NULL;
struct service *s;
-
+
assert(u);
pa_log_debug("Unpublishing services in Zeroconf");
if (rem) {
avahi_entry_group_free(s->entry_group);
s->entry_group = NULL;
- } else
+ } else
avahi_entry_group_reset(s->entry_group);
}
assert(c);
u->client = c;
-
+
switch (state) {
case AVAHI_CLIENT_S_RUNNING:
publish_all_services(u);
break;
-
+
case AVAHI_CLIENT_S_COLLISION:
unpublish_all_services(u, 0);
break;
if (!(u->client = avahi_client_new(u->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, u, &error)))
pa_log("pa_avahi_client_new() failed: %s", avahi_strerror(error));
}
-
+
break;
default: ;
u->port = (uint16_t) port;
u->avahi_poll = pa_avahi_poll_new(c->mainloop);
-
+
u->services = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
u->sink_dynarray = pa_dynarray_new();
u->source_dynarray = pa_dynarray_new();
}
pa_modargs_free(ma);
-
+
return 0;
-
+
fail:
pa__done(c, m);
if (ma)
pa_modargs_free(ma);
-
+
return -1;
}
if (s->entry_group)
avahi_entry_group_free(s->entry_group);
-
+
pa_xfree(s->service_name);
pa_xfree(s->name);
pa_xfree(s);
pa_dynarray_free(u->source_dynarray, NULL, NULL);
if (u->autoload_dynarray)
pa_dynarray_free(u->autoload_dynarray, NULL, NULL);
-
+
if (u->main_entry_group)
avahi_entry_group_free(u->main_entry_group);
-
+
if (u->client)
avahi_client_free(u->client);
-
+
if (u->avahi_poll)
pa_avahi_poll_free(u->avahi_poll);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
if(!pcaps)
pcaps = ∩︀
-
+
if (*mode == O_RDWR) {
if ((fd = open(device, O_RDWR|O_NDELAY)) >= 0) {
int dcaps, *tcaps;
ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0);
tcaps = pcaps ? pcaps : &dcaps;
-
+
if (ioctl(fd, SNDCTL_DSP_GETCAPS, tcaps) < 0) {
pa_log("SNDCTL_DSP_GETCAPS: %s", pa_cstrerror(errno));
goto fail;
close(fd);
}
-
+
if ((fd = open(device, (*mode = O_WRONLY)|O_NDELAY)) < 0) {
if ((fd = open(device, (*mode = O_RDONLY)|O_NDELAY)) < 0) {
pa_log("open('%s'): %s", device, pa_cstrerror(errno));
pa_log("open('%s'): %s", device, pa_cstrerror(errno));
goto fail;
}
- }
+ }
success:
*pcaps = 0;
-
+
if (ioctl(fd, SNDCTL_DSP_GETCAPS, pcaps) < 0) {
pa_log("SNDCTL_DSP_GETCAPS: %s", pa_cstrerror(errno));
goto fail;
}
-
+
pa_log_debug("capabilities:%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
*pcaps & DSP_CAP_BATCH ? " BATCH" : "",
#ifdef DSP_CAP_BIND
#endif
*pcaps & DSP_CAP_COPROC ? " COPROC" : "",
*pcaps & DSP_CAP_DUPLEX ? " DUPLEX" : "",
-#ifdef DSP_CAP_FREERATE
+#ifdef DSP_CAP_FREERATE
*pcaps & DSP_CAP_FREERATE ? " FREERATE" : "",
#else
"",
*pcaps & DSP_CAP_TRIGGER ? " TRIGGER" : "");
pa_fd_set_cloexec(fd, 1);
-
+
return fd;
fail:
int pa_oss_auto_format(int fd, pa_sample_spec *ss) {
int format, channels, speed, reqformat;
pa_sample_format_t orig_format;
-
+
static const int format_trans[PA_SAMPLE_MAX] = {
[PA_SAMPLE_U8] = AFMT_U8,
[PA_SAMPLE_ALAW] = AFMT_A_LAW,
assert(fd >= 0 && ss);
orig_format = ss->format;
-
+
reqformat = format = format_trans[ss->format];
if (reqformat == AFMT_QUERY || ioctl(fd, SNDCTL_DSP_SETFMT, &format) < 0 || format != reqformat) {
format = AFMT_S16_NE;
pa_log_warn("device doesn't support sample format %s, changed to %s.",
pa_sample_format_to_string(orig_format),
pa_sample_format_to_string(ss->format));
-
+
channels = ss->channels;
if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) < 0) {
pa_log("SNDCTL_DSP_CHANNELS: %s", pa_cstrerror(errno));
if (!v) break;
k++;
}
-
+
return k;
}
int pa_oss_set_fragments(int fd, int nfrags, int frag_size) {
int arg;
arg = ((int) nfrags << 16) | simple_log2(frag_size);
-
+
if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &arg) < 0) {
pa_log("SNDCTL_DSP_SETFRAGMENT: %s", pa_cstrerror(errno));
return -1;
assert(fd >= 0);
assert(ss);
assert(volume);
-
+
if (ioctl(fd, mixer, &vol) < 0)
return -1;
r = volume->values[1] > PA_VOLUME_NORM ? PA_VOLUME_NORM : volume->values[1];
vol |= ((r*100)/PA_VOLUME_NORM) << 8;
}
-
+
if (ioctl(fd, mixer, &vol) < 0)
return -1;
n = *e - '0';
else
return -1;
-
+
if (!(f = fopen("/dev/sndstat", "r")) &&
!(f = fopen("/proc/sndstat", "r")) &&
!(f = fopen("/proc/asound/oss/sndstat", "r"))) {
while (!feof(f)) {
char line[64];
int device;
-
+
if (!fgets(line, sizeof(line), f))
break;
if (line[0] == 0)
break;
-
+
if (sscanf(line, "%i: ", &device) != 1)
continue;
if (pa_endswith(k, " (DUPLEX)"))
k[strlen(k)-9] = 0;
-
+
pa_strlcpy(name, k, l);
r = 0;
break;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA.
***/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
#include <assert.h>
#include <string.h>
pa_browser_error_cb_t error_callback;
void *error_userdata;
-
+
AvahiClient *client;
AvahiServiceBrowser *server_browser, *sink_browser, *source_browser;
-
+
};
static int map_to_opcode(const char *type, int new) {
AvahiStringList *txt,
AvahiLookupResultFlags flags,
void *userdata) {
-
+
pa_browser *b = userdata;
pa_browse_info i;
char ip[256], a[256];
pa_sample_spec ss;
int ss_valid = 0;
char *key = NULL, *value = NULL;
-
+
assert(b);
memset(&i, 0, sizeof(i));
if (event != AVAHI_RESOLVER_FOUND)
goto fail;
-
+
if (!b->callback)
goto fail;
while (txt) {
-
+
if (avahi_string_list_get_pair(txt, &key, &value, NULL) < 0)
break;
-
+
if (!strcmp(key, "device")) {
device_found = 1;
pa_xfree((char*) i.device);
value = NULL;
} else if (!strcmp(key, "fqdn")) {
size_t l;
-
+
pa_xfree((char*) i.fqdn);
i.fqdn = value;
value = NULL;
-
+
l = strlen(a);
assert(l+1 <= sizeof(a));
strncat(a, " ", sizeof(a)-l-1);
if (pa_atou(value, &cookie) < 0)
goto fail;
-
+
i.cookie = &cookie;
} else if (!strcmp(key, "description")) {
pa_xfree((char*) i.description);
value = NULL;
} else if (!strcmp(key, "channels")) {
uint32_t ch;
-
+
if (pa_atou(value, &ch) < 0 || ch <= 0 || ch > 255)
goto fail;
-
+
ss.channels = (uint8_t) ch;
ss_valid |= 1;
-
+
} else if (!strcmp(key, "rate")) {
if (pa_atou(value, &ss.rate) < 0)
goto fail;
if ((ss.format = pa_parse_sample_format(value)) == PA_SAMPLE_INVALID)
goto fail;
-
+
ss_valid |= 4;
}
}
/* No device txt record was sent for a sink or source service */
- if (opcode != PA_BROWSE_NEW_SERVER && !device_found)
+ if (opcode != PA_BROWSE_NEW_SERVER && !device_found)
goto fail;
if (ss_valid == 7)
pa_xfree(key);
pa_xfree(value);
-
+
avahi_service_resolver_free(r);
}
break;
}
-
+
case AVAHI_BROWSER_REMOVE: {
if (b->callback) {
pa_browse_info i;
int opcode;
-
+
memset(&i, 0, sizeof(i));
i.name = name;
opcode = map_to_opcode(type, 0);
assert(opcode >= 0);
-
+
b->callback(b, opcode, &i, b->userdata);
}
break;
handle_failure(b);
break;
}
-
+
default:
;
}
if (flags & ~(PA_BROWSE_FOR_SERVERS|PA_BROWSE_FOR_SINKS|PA_BROWSE_FOR_SOURCES) || flags == 0)
return NULL;
-
+
b = pa_xnew(pa_browser, 1);
b->mainloop = mainloop;
b->ref = 1;
*error_string = avahi_strerror(avahi_client_errno(b->client));
goto fail;
}
-
+
if ((flags & PA_BROWSE_FOR_SINKS) &&
!(b->sink_browser = avahi_service_browser_new(
b->client,
*error_string = avahi_strerror(avahi_client_errno(b->client));
goto fail;
}
-
+
return b;
fail:
if (b)
browser_free(b);
-
+
return NULL;
}
if (b->avahi_poll)
pa_avahi_poll_free(b->avahi_poll);
-
+
pa_xfree(b);
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
PA_BROWSE_NEW_SINK, /**< New sink found */
PA_BROWSE_NEW_SOURCE, /**< New source found */
PA_BROWSE_REMOVE_SERVER, /**< Server disappeared */
- PA_BROWSE_REMOVE_SINK, /**< Sink disappeared */
+ PA_BROWSE_REMOVE_SINK, /**< Sink disappeared */
PA_BROWSE_REMOVE_SOURCE /**< Source disappeared */
} pa_browse_opcode_t;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
const char *const table[] = {
[PA_CHANNEL_POSITION_MONO] = "mono",
-
+
[PA_CHANNEL_POSITION_FRONT_CENTER] = "front-center",
[PA_CHANNEL_POSITION_FRONT_LEFT] = "front-left",
[PA_CHANNEL_POSITION_FRONT_RIGHT] = "front-right",
-
+
[PA_CHANNEL_POSITION_REAR_CENTER] = "rear-center",
[PA_CHANNEL_POSITION_REAR_LEFT] = "rear-left",
[PA_CHANNEL_POSITION_REAR_RIGHT] = "rear-right",
-
+
[PA_CHANNEL_POSITION_LFE] = "lfe",
-
+
[PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = "front-left-of-center",
[PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = "front-right-of-center",
-
+
[PA_CHANNEL_POSITION_SIDE_LEFT] = "side-left",
[PA_CHANNEL_POSITION_SIDE_RIGHT] = "side-right",
-
+
[PA_CHANNEL_POSITION_AUX0] = "aux0",
[PA_CHANNEL_POSITION_AUX1] = "aux1",
[PA_CHANNEL_POSITION_AUX2] = "aux2",
[PA_CHANNEL_POSITION_AUX31] = "aux31",
[PA_CHANNEL_POSITION_TOP_CENTER] = "top-center",
-
+
[PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = "top-front-left",
[PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = "top-front-right",
[PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = "top-front-center",
switch (def) {
case PA_CHANNEL_MAP_AIFF:
-
+
/* This is somewhat compatible with RFC3551 */
-
+
switch (channels) {
case 1:
m->map[0] = PA_CHANNEL_POSITION_MONO;
return m;
-
+
case 6:
m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
m->map[1] = PA_CHANNEL_POSITION_SIDE_LEFT;
m->map[4] = PA_CHANNEL_POSITION_SIDE_RIGHT;
m->map[5] = PA_CHANNEL_POSITION_LFE;
return m;
-
+
case 5:
m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
m->map[3] = PA_CHANNEL_POSITION_REAR_LEFT;
m->map[4] = PA_CHANNEL_POSITION_REAR_RIGHT;
/* Fall through */
-
+
case 2:
m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
return m;
-
+
case 3:
m->map[0] = PA_CHANNEL_POSITION_LEFT;
m->map[1] = PA_CHANNEL_POSITION_RIGHT;
m->map[2] = PA_CHANNEL_POSITION_CENTER;
return m;
-
+
case 4:
m->map[0] = PA_CHANNEL_POSITION_LEFT;
m->map[1] = PA_CHANNEL_POSITION_CENTER;
m->map[2] = PA_CHANNEL_POSITION_RIGHT;
m->map[3] = PA_CHANNEL_POSITION_LFE;
return m;
-
+
default:
return NULL;
}
case 1:
m->map[0] = PA_CHANNEL_POSITION_MONO;
return m;
-
+
case 8:
m->map[6] = PA_CHANNEL_POSITION_SIDE_LEFT;
m->map[7] = PA_CHANNEL_POSITION_SIDE_RIGHT;
/* Fall through */
-
+
case 6:
m->map[5] = PA_CHANNEL_POSITION_LFE;
/* Fall through */
-
+
case 5:
m->map[4] = PA_CHANNEL_POSITION_FRONT_CENTER;
/* Fall through */
-
+
case 4:
m->map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
m->map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
/* Fall through */
-
+
case 2:
m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
return m;
-
+
default:
return NULL;
}
case PA_CHANNEL_MAP_AUX: {
unsigned i;
-
+
if (channels >= PA_CHANNELS_MAX)
return NULL;
for (i = 0; i < channels; i++)
m->map[i] = PA_CHANNEL_POSITION_AUX0 + i;
-
+
return m;
}
case 1:
m->map[0] = PA_CHANNEL_POSITION_MONO;
return m;
-
+
case 18:
m->map[15] = PA_CHANNEL_POSITION_TOP_REAR_LEFT;
m->map[16] = PA_CHANNEL_POSITION_TOP_REAR_CENTER;
m->map[17] = PA_CHANNEL_POSITION_TOP_REAR_RIGHT;
/* Fall through */
-
+
case 15:
m->map[12] = PA_CHANNEL_POSITION_TOP_FRONT_LEFT;
m->map[13] = PA_CHANNEL_POSITION_TOP_FRONT_CENTER;
m->map[14] = PA_CHANNEL_POSITION_TOP_FRONT_RIGHT;
/* Fall through */
-
+
case 12:
m->map[11] = PA_CHANNEL_POSITION_TOP_CENTER;
/* Fall through */
-
+
case 11:
m->map[9] = PA_CHANNEL_POSITION_SIDE_LEFT;
m->map[10] = PA_CHANNEL_POSITION_SIDE_RIGHT;
/* Fall through */
-
+
case 9:
m->map[8] = PA_CHANNEL_POSITION_REAR_CENTER;
/* Fall through */
-
+
case 8:
m->map[6] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
m->map[7] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
/* Fall through */
-
+
case 6:
m->map[4] = PA_CHANNEL_POSITION_REAR_LEFT;
m->map[5] = PA_CHANNEL_POSITION_REAR_RIGHT;
/* Fall through */
-
+
case 4:
m->map[3] = PA_CHANNEL_POSITION_LFE;
/* Fall through */
-
+
case 3:
m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
/* Fall through */
-
+
case 2:
m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
return m;
-
+
default:
return NULL;
}
case 1:
m->map[0] = PA_CHANNEL_POSITION_MONO;
return m;
-
+
case 8:
m->map[6] = PA_CHANNEL_POSITION_REAR_LEFT;
m->map[7] = PA_CHANNEL_POSITION_REAR_RIGHT;
/* Fall through */
-
+
case 6:
m->map[4] = PA_CHANNEL_POSITION_SIDE_LEFT;
m->map[5] = PA_CHANNEL_POSITION_SIDE_RIGHT;
case 4:
m->map[3] = PA_CHANNEL_POSITION_LFE;
/* Fall through */
-
+
case 3:
m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
/* Fall through */
-
+
case 2:
m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
return m;
-
+
default:
return NULL;
}
-
+
default:
return NULL;
int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b) {
unsigned c;
-
+
assert(a);
assert(b);
if (a->channels != b->channels)
return 0;
-
+
for (c = 0; c < a->channels; c++)
if (a->map[c] != b->map[c])
return 0;
unsigned channel;
int first = 1;
char *e;
-
+
assert(s);
assert(l > 0);
assert(map);
const char *state;
pa_channel_map map;
char *p;
-
+
assert(rmap);
assert(s);
state = NULL;
map.channels = 0;
-
+
while ((p = pa_split(s, ",", &state))) {
if (map.channels >= PA_CHANNELS_MAX) {
pa_xfree(p);
return NULL;
}
-
+
/* Some special aliases */
if (strcmp(p, "left") == 0)
map.map[map.channels++] = PA_CHANNEL_POSITION_LEFT;
map.map[map.channels++] = PA_CHANNEL_POSITION_SUBWOOFER;
else {
pa_channel_position_t i;
-
+
for (i = 0; i < PA_CHANNEL_POSITION_MAX; i++)
if (strcmp(p, table[i]) == 0) {
map.map[map.channels++] = i;
break;
}
-
+
if (i >= PA_CHANNEL_POSITION_MAX) {
pa_xfree(p);
return NULL;
}
finish:
-
+
if (!pa_channel_map_valid(&map))
return NULL;
-
+
*rmap = map;
return rmap;
}
int pa_channel_map_valid(const pa_channel_map *map) {
unsigned c;
-
+
assert(map);
if (map->channels <= 0 || map->channels > PA_CHANNELS_MAX)
return 0;
for (c = 0; c < map->channels; c++) {
-
+
if (map->map[c] < 0 ||map->map[c] >= PA_CHANNEL_POSITION_MAX)
return 0;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
PA_CHANNEL_POSITION_LEFT,
PA_CHANNEL_POSITION_RIGHT,
PA_CHANNEL_POSITION_CENTER,
-
+
PA_CHANNEL_POSITION_FRONT_LEFT = PA_CHANNEL_POSITION_LEFT,
PA_CHANNEL_POSITION_FRONT_RIGHT = PA_CHANNEL_POSITION_RIGHT,
PA_CHANNEL_POSITION_FRONT_CENTER = PA_CHANNEL_POSITION_CENTER,
PA_CHANNEL_POSITION_REAR_CENTER,
PA_CHANNEL_POSITION_REAR_LEFT,
PA_CHANNEL_POSITION_REAR_RIGHT,
-
+
PA_CHANNEL_POSITION_LFE,
PA_CHANNEL_POSITION_SUBWOOFER = PA_CHANNEL_POSITION_LFE,
-
+
PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER,
PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER,
-
+
PA_CHANNEL_POSITION_SIDE_LEFT,
PA_CHANNEL_POSITION_SIDE_RIGHT,
PA_CHANNEL_POSITION_AUX31,
PA_CHANNEL_POSITION_TOP_CENTER,
-
+
PA_CHANNEL_POSITION_TOP_FRONT_LEFT,
PA_CHANNEL_POSITION_TOP_FRONT_RIGHT,
PA_CHANNEL_POSITION_TOP_FRONT_CENTER,
PA_CHANNEL_POSITION_TOP_REAR_LEFT,
PA_CHANNEL_POSITION_TOP_REAR_RIGHT,
PA_CHANNEL_POSITION_TOP_REAR_CENTER,
-
+
PA_CHANNEL_POSITION_MAX
} pa_channel_position_t;
PA_CHANNEL_MAP_AUX, /**< Only aux channels */
PA_CHANNEL_MAP_WAVEEX, /**< Microsoft's WAVEFORMATEXTENSIBLE mapping */
PA_CHANNEL_MAP_OSS, /**< The default channel mapping used by OSS as defined in the OSS 4.0 API specs */
-
+
PA_CHANNEL_MAP_DEFAULT = PA_CHANNEL_MAP_AIFF /**< The default channel map */
} pa_channel_map_def_t;
if (!dname && !getenv("DISPLAY"))
goto finish;
-
+
if (!(d = XOpenDisplay(dname))) {
pa_log("XOpenDisplay() failed");
goto finish;
XCloseDisplay(d);
return ret;
-
+
}
pa_client_conf *pa_client_conf_new(void) {
pa_client_conf *c = pa_xmemdup(&default_conf, sizeof(default_conf));
-
+
c->daemon_binary = pa_xstrdup(PA_BINARY);
c->extra_arguments = pa_xstrdup("--log-target=syslog --exit-idle-time=5");
c->cookie_file = pa_xstrdup(PA_NATIVE_COOKIE_FILE);
-
+
return c;
}
pa_log("WARNING: failed to open configuration file '%s': %s", fn, pa_cstrerror(errno));
goto finish;
}
-
+
r = f ? pa_config_parse(fn, f, table, NULL) : 0;
if (!r)
r = pa_client_conf_load_cookie(c);
-
+
finish:
pa_xfree(fn);
if (f)
fclose(f);
-
+
return r;
}
int pa_client_conf_env(pa_client_conf *c) {
char *e;
-
+
if ((e = getenv(ENV_DEFAULT_SINK))) {
pa_xfree(c->default_sink);
c->default_sink = pa_xstrdup(e);
pa_xfree(c->default_server);
c->default_server = pa_xstrdup(e);
}
-
+
if ((e = getenv(ENV_DAEMON_BINARY))) {
pa_xfree(c->daemon_binary);
c->daemon_binary = pa_xstrdup(e);
return pa_client_conf_load_cookie(c);
}
-
+
return 0;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
static void unlock_autospawn_lock_file(pa_context *c) {
assert(c);
-
+
if (c->autospawn_lock_fd >= 0) {
char lf[PATH_MAX];
pa_runtime_path(AUTOSPAWN_LOCK, lf, sizeof(lf));
-
+
pa_unlock_lockfile(lf, c->autospawn_lock_fd);
c->autospawn_lock_fd = -1;
}
pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) {
pa_context *c;
-
+
assert(mainloop);
assert(name);
-
+
c = pa_xnew(pa_context, 1);
c->ref = 1;
c->name = pa_xstrdup(name);
PA_LLIST_HEAD_INIT(pa_stream, c->streams);
PA_LLIST_HEAD_INIT(pa_operation, c->operations);
-
+
c->error = PA_OK;
c->state = PA_CONTEXT_UNCONNECTED;
c->ctag = 0;
c->do_autospawn = 0;
#ifndef MSG_NOSIGNAL
-#ifdef SIGPIPE
+#ifdef SIGPIPE
pa_check_signal_is_blocked(SIGPIPE);
#endif
#endif
pa_pstream_close(c->pstream);
pa_pstream_unref(c->pstream);
}
-
+
if (c->record_streams)
pa_dynarray_free(c->record_streams, NULL, NULL);
if (c->playback_streams)
pa_client_conf_free(c->conf);
pa_strlist_free(c->server_list);
-
+
pa_xfree(c->name);
pa_xfree(c->server);
pa_xfree(c);
pa_context* pa_context_ref(pa_context *c) {
assert(c);
assert(c->ref >= 1);
-
+
c->ref++;
return c;
}
void pa_context_set_state(pa_context *c, pa_context_state_t st) {
assert(c);
assert(c->ref >= 1);
-
+
if (c->state == st)
return;
if (st == PA_CONTEXT_FAILED || st == PA_CONTEXT_TERMINATED) {
pa_stream *s;
-
+
s = c->streams ? pa_stream_ref(c->streams) : NULL;
while (s) {
pa_stream *n = s->next ? pa_stream_ref(s->next) : NULL;
if (c->pdispatch)
pa_pdispatch_unref(c->pdispatch);
c->pdispatch = NULL;
-
+
if (c->pstream) {
pa_pstream_close(c->pstream);
pa_pstream_unref(c->pstream);
}
c->pstream = NULL;
-
+
if (c->client)
pa_socket_client_unref(c->client);
c->client = NULL;
void pa_context_fail(pa_context *c, int error) {
assert(c);
assert(c->ref >= 1);
-
+
pa_context_set_error(c, error);
pa_context_set_state(c, PA_CONTEXT_FAILED);
}
assert(p);
assert(c);
-
+
pa_context_fail(c, PA_ERR_CONNECTIONTERMINATED);
}
static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_creds *creds, void *userdata) {
pa_context *c = userdata;
-
+
assert(p);
assert(packet);
assert(c);
pa_context_ref(c);
-
+
if (pa_pdispatch_run(c->pdispatch, packet, creds, c) < 0)
pa_context_fail(c, PA_ERR_PROTOCOL);
static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata) {
pa_context *c = userdata;
pa_stream *s;
-
+
assert(p);
assert(chunk);
assert(chunk->memblock);
pa_memblockq_seek(s->record_memblockq, offset, seek);
pa_memblockq_push_align(s->record_memblockq, chunk);
-
+
if (s->read_callback) {
size_t l;
if (command == PA_COMMAND_ERROR) {
assert(t);
-
+
if (pa_tagstruct_getu32(t, &c->error) < 0) {
pa_context_fail(c, PA_ERR_PROTOCOL);
return -1;
-
+
}
} else if (command == PA_COMMAND_TIMEOUT)
c->error = PA_ERR_TIMEOUT;
static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
pa_context *c = userdata;
-
+
assert(pd);
assert(c);
assert(c->state == PA_CONTEXT_AUTHORIZING || c->state == PA_CONTEXT_SETTING_NAME);
pa_context_ref(c);
-
+
if (command != PA_COMMAND_REPLY) {
-
+
if (pa_context_handle_error(c, command, t) < 0)
pa_context_fail(c, PA_ERR_PROTOCOL);
* user. This is a security measure because otherwise
* data private to the user might leak. */
-#ifdef HAVE_CREDS
+#ifdef HAVE_CREDS
const pa_creds *creds;
if ((creds = pa_pdispatch_creds(pd)))
if (getuid() == creds->uid)
case PA_CONTEXT_SETTING_NAME :
pa_context_set_state(c, PA_CONTEXT_READY);
break;
-
+
default:
assert(0);
}
static void setup_context(pa_context *c, pa_iochannel *io) {
pa_tagstruct *t;
uint32_t tag;
-
+
assert(c);
assert(io);
pa_context_ref(c);
-
+
assert(!c->pstream);
c->pstream = pa_pstream_new(c->mainloop, io, c->mempool);
ucred.uid = getuid();
ucred.gid = getgid();
-
+
pa_pstream_send_tagstruct_with_creds(c->pstream, t, &ucred);
}
#else
pa_pstream_send_tagstruct(c->pstream, t);
#endif
-
+
pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, setup_complete_callback, c, NULL);
pa_context_set_state(c, PA_CONTEXT_AUTHORIZING);
pa_iochannel *io;
pa_context_ref(c);
-
+
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) {
pa_log("socketpair(): %s", pa_cstrerror(errno));
pa_context_fail(c, PA_ERR_INTERNAL);
}
pa_fd_set_cloexec(fds[0], 1);
-
+
pa_socket_low_delay(fds[0]);
pa_socket_low_delay(fds[1]);
if (c->spawn_api.postfork)
c->spawn_api.postfork();
-
+
goto fail;
} else if (!pid) {
/* Child */
/* Not required, since fds[0] has CLOEXEC enabled anyway */
close(fds[0]);
-
+
if (c->spawn_api.atfork)
c->spawn_api.atfork();
/* Setup argv */
n = 0;
-
+
argv[n++] = c->conf->daemon_binary;
argv[n++] = "--daemonize=yes";
-
+
snprintf(t, sizeof(t), "-Lmodule-native-protocol-fd fd=%i", fds[1]);
argv[n++] = strdup(t);
if (!(a = pa_split_spaces(c->conf->extra_arguments, &state)))
break;
-
+
argv[n++] = a;
}
execv(argv[0], (char * const *) argv);
_exit(1);
#undef MAX_ARGS
- }
+ }
/* Parent */
if (c->spawn_api.postfork)
c->spawn_api.postfork();
-
+
if (r < 0) {
pa_log("waitpid(): %s", pa_cstrerror(errno));
pa_context_fail(c, PA_ERR_INTERNAL);
close(fds[1]);
c->is_local = 1;
-
+
io = pa_iochannel_new(c->mainloop, fds[0], fds[0]);
setup_context(c, io);
static int try_next_connection(pa_context *c) {
char *u = NULL;
int r = -1;
-
+
assert(c);
assert(!c->client);
for (;;) {
pa_xfree(u);
u = NULL;
-
+
c->server_list = pa_strlist_pop(c->server_list, &u);
-
+
if (!u) {
#ifndef OS_IS_WIN32
goto finish;
}
#endif
-
+
pa_context_fail(c, PA_ERR_CONNECTIONREFUSED);
goto finish;
}
-
- pa_log_debug("Trying to connect to %s...", u);
+
+ pa_log_debug("Trying to connect to %s...", u);
pa_xfree(c->server);
c->server = pa_xstrdup(u);
if (!(c->client = pa_socket_client_new_string(c->mainloop, u, PA_NATIVE_DEFAULT_PORT)))
continue;
-
+
c->is_local = pa_socket_client_is_local(c->client);
pa_socket_client_set_callback(c->client, on_connection, c);
break;
finish:
pa_xfree(u);
-
+
return r;
}
static void on_connection(pa_socket_client *client, pa_iochannel*io, void *userdata) {
pa_context *c = userdata;
-
+
assert(client);
assert(c);
assert(c->state == PA_CONTEXT_CONNECTING);
const char *server,
pa_context_flags_t flags,
const pa_spawn_api *api) {
-
+
int r = -1;
-
+
assert(c);
assert(c->ref >= 1);
pa_context_ref(c);
assert(!c->server_list);
-
+
if (server) {
if (!(c->server_list = pa_strlist_parse(server))) {
pa_context_fail(c, PA_ERR_INVALIDSERVER);
char ufn[PATH_MAX];
/* Prepend in reverse order */
-
+
if ((d = getenv("DISPLAY"))) {
char *e;
d = pa_xstrdup(d);
pa_xfree(d);
}
-
+
c->server_list = pa_strlist_prepend(c->server_list, "tcp6:localhost");
c->server_list = pa_strlist_prepend(c->server_list, "tcp4:localhost");
pa_context_set_state(c, PA_CONTEXT_CONNECTING);
r = try_next_connection(c);
-
+
finish:
pa_context_unref(c);
-
+
return r;
}
void pa_context_disconnect(pa_context *c) {
assert(c);
assert(c->ref >= 1);
-
+
pa_context_set_state(c, PA_CONTEXT_TERMINATED);
}
pa_context_state_t pa_context_get_state(pa_context *c) {
assert(c);
assert(c->ref >= 1);
-
+
return c->state;
}
int pa_context_errno(pa_context *c) {
assert(c);
assert(c->ref >= 1);
-
+
return c->error;
}
void pa_context_set_state_callback(pa_context *c, pa_context_notify_cb_t cb, void *userdata) {
assert(c);
assert(c->ref >= 1);
-
+
c->state_callback = cb;
c->state_userdata = userdata;
}
static void set_dispatch_callbacks(pa_operation *o) {
int done = 1;
-
+
assert(o);
assert(o->ref >= 1);
assert(o->context);
pa_pstream_set_drain_callback(o->context->pstream, NULL, NULL);
pa_pdispatch_set_drain_callback(o->context->pdispatch, NULL, NULL);
-
+
if (pa_pdispatch_is_pending(o->context->pdispatch)) {
pa_pdispatch_set_drain_callback(o->context->pdispatch, pdispatch_drain_callback, o);
done = 0;
pa_context_notify_cb_t cb = (pa_context_notify_cb_t) o->callback;
cb(o->context, o->userdata);
}
-
+
pa_operation_done(o);
pa_operation_unref(o);
}
pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *userdata) {
pa_operation *o;
-
+
assert(c);
assert(c->ref >= 1);
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY_RETURN_NULL(c, pa_context_is_pending(c), PA_ERR_BADSTATE);
-
+
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
set_dispatch_callbacks(pa_operation_ref(o));
void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
pa_operation *o = userdata;
int success = 1;
-
+
assert(pd);
assert(o);
assert(o->ref >= 1);
pa_tagstruct *t;
pa_operation *o;
uint32_t tag;
-
+
assert(c);
assert(c->ref >= 1);
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
+
o = pa_operation_new(c, NULL, cb, userdata);
t = pa_tagstruct_command(c, command, &tag);
pa_tagstruct *t;
pa_operation *o;
uint32_t tag;
-
+
assert(c);
assert(c->ref >= 1);
assert(c->ref >= 1);
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
+
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
t = pa_tagstruct_command(c, PA_COMMAND_SET_DEFAULT_SOURCE, &tag);
int pa_context_is_local(pa_context *c) {
assert(c);
-
+
return c->is_local;
}
assert(name);
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
+
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
t = pa_tagstruct_command(c, PA_COMMAND_SET_CLIENT_NAME, &tag);
if (!c->server)
return NULL;
-
+
if (*c->server == '{') {
char *e = strchr(c->server+1, '}');
return e ? e+1 : c->server;
}
-
+
return c->server;
}
assert(c);
assert(tag);
-
+
t = pa_tagstruct_new(NULL, 0);
pa_tagstruct_putu32(t, command);
pa_tagstruct_putu32(t, *tag = c->ctag++);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* The abstraction is represented as a number of function pointers in the
* pa_mainloop_api structure.
*
- * To actually be able to use these functions, an implementation needs to
+ * To actually be able to use these functions, an implementation needs to
* be coupled to the abstraction. There are three of these shipped with
* PulseAudio, but any other can be used with a minimal ammount of work,
* provided it supports the three basic events listed above.
* and decrease their reference counts. Whenever an object's reference
* count reaches zero, that object gets destroy and any resources it uses
* get freed.
- *
+ *
* The benefit of this design is that an application need not worry about
* whether or not it needs to keep an object around in case the library is
* using it internally. If it is, then it has made sure it has its own
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
PA_CONTEXT_NOAUTOSPAWN = 1 /**< Disabled autospawning of the PulseAudio daemon if required */
} pa_context_flags_t;
-/** The direction of a pa_stream object */
+/** The direction of a pa_stream object */
typedef enum pa_stream_direction {
PA_STREAM_NODIRECTION, /**< Invalid direction */
PA_STREAM_PLAYBACK, /**< Playback stream */
PA_ERR_EXIST, /**< Entity exists */
PA_ERR_NOENTITY, /**< No such entity */
PA_ERR_CONNECTIONREFUSED, /**< Connection refused */
- PA_ERR_PROTOCOL, /**< Protocol error */
+ PA_ERR_PROTOCOL, /**< Protocol error */
PA_ERR_TIMEOUT, /**< Timeout */
PA_ERR_AUTHKEY, /**< No authorization key */
PA_ERR_INTERNAL, /**< Internal error */
* total output latency a sample that is written with
* pa_stream_write() takes to be played may be estimated by
* sink_usec+buffer_usec+transport_usec. (where buffer_usec is defined
- * as pa_bytes_to_usec(write_index-read_index)) The output buffer
+ * as pa_bytes_to_usec(write_index-read_index)) The output buffer
* which buffer_usec relates to may be manipulated freely (with
* pa_stream_write()'s seek argument, pa_stream_flush() and friends),
* the buffers sink_usec and source_usec relate to are first-in
* flush request that corrupted it has
* been issued in the time since this
* latency info was current. \since 0.8 */
-
+
int64_t read_index; /**< Current read index into the
* playback buffer in bytes. Think twice before
* using this for seeking purposes: it
/** Seek type for pa_stream_write(). \since 0.8*/
typedef enum pa_seek_mode {
PA_SEEK_RELATIVE = 0, /**< Seek relatively to the write index */
- PA_SEEK_ABSOLUTE = 1, /**< Seek relatively to the start of the buffer queue */
+ PA_SEEK_ABSOLUTE = 1, /**< Seek relatively to the start of the buffer queue */
PA_SEEK_RELATIVE_ON_READ = 2, /**< Seek relatively to the read index. */
PA_SEEK_RELATIVE_END = 3 /**< Seek relatively to the current end of the buffer queue. */
} pa_seek_mode_t;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
int dead;
int enabled;
-
+
pa_defer_event_cb_t callback;
void *userdata;
pa_defer_event_destroy_cb_t destroy_callback;
struct pa_glib_mainloop {
GSource source;
-
+
pa_mainloop_api api;
GMainContext *context;
if (!force && g->io_events_please_scan <= 0)
break;
-
+
if (force || e->dead) {
PA_LLIST_REMOVE(pa_io_event, g->io_events, e);
g_assert(g->io_events_please_scan > 0);
g->io_events_please_scan--;
}
-
+
if (e->poll_fd_added)
g_source_remove_poll(&g->source, &e->poll_fd);
-
+
if (e->destroy_callback)
e->destroy_callback(&g->api, e, e->userdata);
-
+
pa_xfree(e);
}
if (!force && g->time_events_please_scan <= 0)
break;
-
+
if (force || e->dead) {
PA_LLIST_REMOVE(pa_time_event, g->time_events, e);
g_assert(g->n_enabled_time_events > 0);
g->n_enabled_time_events--;
}
-
+
if (e->destroy_callback)
e->destroy_callback(&g->api, e, e->userdata);
-
+
pa_xfree(e);
}
if (!force && g->defer_events_please_scan <= 0)
break;
-
+
if (force || e->dead) {
PA_LLIST_REMOVE(pa_defer_event, g->defer_events, e);
g_assert(g->n_enabled_defer_events > 0);
g->n_enabled_defer_events--;
}
-
+
if (e->destroy_callback)
e->destroy_callback(&g->api, e, e->userdata);
-
+
pa_xfree(e);
}
pa_io_event_flags_t f,
pa_io_event_cb_t cb,
void *userdata) {
-
+
pa_io_event *e;
pa_glib_mainloop *g;
g_assert(m->userdata);
g_assert(fd >= 0);
g_assert(cb);
-
+
g = m->userdata;
e = pa_xnew(pa_io_event, 1);
e->poll_fd.fd = fd;
e->poll_fd.events = map_flags_to_glib(f);
e->poll_fd.revents = 0;
-
+
e->callback = cb;
e->userdata = userdata;
e->destroy_callback = NULL;
g_source_add_poll(&g->source, &e->poll_fd);
e->poll_fd_added = 1;
-
+
return e;
}
static void glib_io_set_destroy(pa_io_event*e, pa_io_event_destroy_cb_t cb) {
g_assert(e);
g_assert(!e->dead);
-
+
e->destroy_callback = cb;
}
const struct timeval *tv,
pa_time_event_cb_t cb,
void *userdata) {
-
+
pa_glib_mainloop *g;
pa_time_event *e;
-
+
g_assert(m);
g_assert(m->userdata);
g_assert(cb);
-
+
g = m->userdata;
e = pa_xnew(pa_time_event, 1);
g->cached_next_time_event = e;
}
}
-
+
e->callback = cb;
e->userdata = userdata;
e->destroy_callback = NULL;
PA_LLIST_PREPEND(pa_time_event, g->time_events, e);
-
+
return e;
}
} else if (!e->enabled && tv)
e->mainloop->n_enabled_time_events++;
- if ((e->enabled = !!tv))
+ if ((e->enabled = !!tv))
e->timeval = *tv;
if (e->mainloop->cached_next_time_event && e->enabled) {
g_assert(e->mainloop->cached_next_time_event->enabled);
-
+
if (pa_timeval_cmp(tv, &e->mainloop->cached_next_time_event->timeval) < 0)
e->mainloop->cached_next_time_event = e;
} else if (e->mainloop->cached_next_time_event == e)
static void glib_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb_t cb) {
g_assert(e);
g_assert(!e->dead);
-
+
e->destroy_callback = cb;
}
pa_mainloop_api*m,
pa_defer_event_cb_t cb,
void *userdata) {
-
+
pa_defer_event *e;
pa_glib_mainloop *g;
g_assert(m);
g_assert(m->userdata);
g_assert(cb);
-
+
g = m->userdata;
-
+
e = pa_xnew(pa_defer_event, 1);
e->mainloop = g;
e->dead = 0;
e->enabled = 1;
g->n_enabled_defer_events++;
-
+
e->callback = cb;
e->userdata = userdata;
e->destroy_callback = NULL;
-
+
PA_LLIST_PREPEND(pa_defer_event, g->defer_events, e);
return e;
}
static void glib_quit(pa_mainloop_api*a, PA_GCC_UNUSED int retval) {
g_warning("quit() ignored");
-
+
/* NOOP */
}
if (g->cached_next_time_event)
return g->cached_next_time_event;
-
+
for (t = g->time_events; t; t = t->next) {
if (t->dead || !t->enabled)
static void scan_dead(pa_glib_mainloop *g) {
g_assert(g);
-
+
if (g->io_events_please_scan)
cleanup_io_events(g, 0);
if (pa_timeval_cmp(&t->timeval, &tvnow) <= 0) {
*timeout = 0;
return TRUE;
- }
+ }
usec = pa_timeval_diff(&t->timeval, &tvnow);
*timeout = (gint) (usec / 1000);
} else
pa_time_event *t;
GTimeVal now;
struct timeval tvnow;
-
+
t = find_next_time_event(g);
g_assert(t);
-
+
g_source_get_current_time(source, &now);
tvnow.tv_sec = now.tv_sec;
tvnow.tv_usec = now.tv_usec;
}
g_assert(d);
-
+
d->callback(&g->api, d, d->userdata);
return TRUE;
}
t = find_next_time_event(g);
g_assert(t);
-
+
g_source_get_current_time(source, &now);
tvnow.tv_sec = now.tv_sec;
tvnow.tv_usec = now.tv_usec;
/* Disable time event */
glib_time_restart(t, NULL);
-
+
t->callback(&g->api, t, &t->timeval, t->userdata);
return TRUE;
}
.time_restart = glib_time_restart,
.time_free = glib_time_free,
.time_set_destroy = glib_time_set_destroy,
-
+
.defer_new = glib_defer_new,
.defer_enable = glib_defer_enable,
.defer_free = glib_defer_free,
.defer_set_destroy = glib_defer_set_destroy,
-
+
.quit = glib_quit,
};
NULL,
NULL
};
-
+
g = (pa_glib_mainloop*) g_source_new(&source_funcs, sizeof(pa_glib_mainloop));
g_main_context_ref(g->context = c ? c : g_main_context_default());
-
+
g->api = vtable;
g->api.userdata = g;
g->io_events_please_scan = g->time_events_please_scan = g->defer_events_please_scan = 0;
g->cached_next_time_event = NULL;
-
+
g_source_attach(&g->source, g->context);
g_source_set_can_recurse(&g->source, FALSE);
-
+
return g;
}
pa_mainloop_api* pa_glib_mainloop_get_api(pa_glib_mainloop *g) {
g_assert(g);
-
+
return &g->api;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
struct pa_context {
int ref;
-
+
char *name;
pa_mainloop_api* mainloop;
int do_autospawn;
int autospawn_lock_fd;
pa_spawn_api spawn_api;
-
+
pa_strlist *server_list;
char *server;
uint32_t device_index;
pa_stream_direction_t direction;
pa_stream_state_t state;
-
+
uint32_t requested_bytes;
pa_memchunk peek_memchunk;
/* Store latest latency info */
pa_timing_info timing_info;
int timing_info_valid;
-
+
/* Use to make sure that time advances monotonically */
pa_usec_t previous_time;
-
+
/* time updates with tags older than these are invalid */
uint32_t write_index_not_before;
uint32_t read_index_not_before;
/* Latency interpolation stuff */
pa_time_event *auto_timing_update_event;
int auto_timing_update_requested;
-
+
pa_usec_t cached_time;
int cached_time_valid;
int ref;
pa_context *context;
pa_stream *stream;
-
+
PA_LLIST_FIELDS(pa_operation);
pa_operation_state_t state;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
static void context_stat_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
pa_operation *o = userdata;
pa_stat_info i, *p = &i;
-
+
assert(pd);
assert(o);
assert(o->ref >= 1);
static void context_get_server_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
pa_operation *o = userdata;
pa_server_info i, *p = &i;
-
+
assert(pd);
assert(o);
assert(o->ref >= 1);
-
+
if (!o->context)
goto finish;
pa_context_fail(o->context, PA_ERR_PROTOCOL);
goto finish;
}
-
+
if (o->callback) {
pa_server_info_cb_t cb = (pa_server_info_cb_t) o->callback;
cb(o->context, p, o->userdata);
static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
pa_operation *o = userdata;
int eol = 1;
-
+
assert(pd);
assert(o);
assert(o->ref >= 1);
if (!o->context)
goto finish;
-
+
if (command != PA_COMMAND_REPLY) {
if (pa_context_handle_error(o->context, command, t) < 0)
goto finish;
eol = -1;
} else {
uint32_t flags;
-
+
while (!pa_tagstruct_eof(t)) {
pa_sink_info i;
-
+
if (pa_tagstruct_getu32(t, &i.index) < 0 ||
pa_tagstruct_gets(t, &i.name) < 0 ||
pa_tagstruct_gets(t, &i.description) < 0 ||
pa_tagstruct_get_usec(t, &i.latency) < 0 ||
pa_tagstruct_gets(t, &i.driver) < 0 ||
pa_tagstruct_getu32(t, &flags) < 0) {
-
+
pa_context_fail(o->context, PA_ERR_PROTOCOL);
goto finish;
}
}
}
}
-
+
if (o->callback) {
pa_sink_info_cb_t cb = (pa_sink_info_cb_t) o->callback;
cb(o->context, NULL, eol, o->userdata);
pa_tagstruct *t;
pa_operation *o;
uint32_t tag;
-
+
assert(c);
assert(c->ref >= 1);
assert(cb);
pa_tagstruct *t;
pa_operation *o;
uint32_t tag;
-
+
assert(c);
assert(c->ref >= 1);
assert(cb);
eol = -1;
} else {
-
+
while (!pa_tagstruct_eof(t)) {
pa_source_info i;
uint32_t flags;
-
+
if (pa_tagstruct_getu32(t, &i.index) < 0 ||
pa_tagstruct_gets(t, &i.name) < 0 ||
pa_tagstruct_gets(t, &i.description) < 0 ||
pa_tagstruct_get_usec(t, &i.latency) < 0 ||
pa_tagstruct_gets(t, &i.driver) < 0 ||
pa_tagstruct_getu32(t, &flags) < 0) {
-
+
pa_context_fail(o->context, PA_ERR_PROTOCOL);
goto finish;
}
}
}
}
-
+
if (o->callback) {
pa_source_info_cb_t cb = (pa_source_info_cb_t) o->callback;
cb(o->context, NULL, eol, o->userdata);
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
-
+
t = pa_tagstruct_command(c, PA_COMMAND_GET_SOURCE_INFO, &tag);
pa_tagstruct_putu32(t, idx);
pa_tagstruct_puts(t, NULL);
eol = -1;
} else {
-
+
while (!pa_tagstruct_eof(t)) {
pa_client_info i;
-
+
if (pa_tagstruct_getu32(t, &i.index) < 0 ||
pa_tagstruct_gets(t, &i.name) < 0 ||
pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
}
}
}
-
+
if (o->callback) {
pa_client_info_cb_t cb = (pa_client_info_cb_t) o->callback;
cb(o->context, NULL, eol, o->userdata);
if (!o->context)
goto finish;
-
+
if (command != PA_COMMAND_REPLY) {
if (pa_context_handle_error(o->context, command, t) < 0)
goto finish;
eol = -1;
} else {
-
+
while (!pa_tagstruct_eof(t)) {
pa_module_info i;
-
+
if (pa_tagstruct_getu32(t, &i.index) < 0 ||
pa_tagstruct_gets(t, &i.name) < 0 ||
pa_tagstruct_gets(t, &i.argument) < 0 ||
}
}
}
-
+
if (o->callback) {
pa_module_info_cb_t cb = (pa_module_info_cb_t) o->callback;
cb(o->context, NULL, eol, o->userdata);
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
-
+
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
t = pa_tagstruct_command(c, PA_COMMAND_GET_MODULE_INFO, &tag);
if (!o->context)
goto finish;
-
+
if (command != PA_COMMAND_REPLY) {
if (pa_context_handle_error(o->context, command, t) < 0)
goto finish;
eol = -1;
} else {
-
+
while (!pa_tagstruct_eof(t)) {
pa_sink_input_info i;
-
+
if (pa_tagstruct_getu32(t, &i.index) < 0 ||
pa_tagstruct_gets(t, &i.name) < 0 ||
pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
pa_tagstruct_get_usec(t, &i.sink_usec) < 0 ||
pa_tagstruct_gets(t, &i.resample_method) < 0 ||
pa_tagstruct_gets(t, &i.driver) < 0) {
-
+
pa_context_fail(o->context, PA_ERR_PROTOCOL);
goto finish;
}
}
}
}
-
+
if (o->callback) {
pa_sink_input_info_cb_t cb = (pa_sink_input_info_cb_t) o->callback;
cb(o->context, NULL, eol, o->userdata);
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
-
+
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
t = pa_tagstruct_command(c, PA_COMMAND_GET_SINK_INPUT_INFO, &tag);
eol = -1;
} else {
-
+
while (!pa_tagstruct_eof(t)) {
pa_source_output_info i;
-
+
if (pa_tagstruct_getu32(t, &i.index) < 0 ||
pa_tagstruct_gets(t, &i.name) < 0 ||
pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
pa_tagstruct_get_usec(t, &i.source_usec) < 0 ||
pa_tagstruct_gets(t, &i.resample_method) < 0 ||
pa_tagstruct_gets(t, &i.driver) < 0) {
-
+
pa_context_fail(o->context, PA_ERR_PROTOCOL);
goto finish;
}
}
}
}
-
+
if (o->callback) {
pa_source_output_info_cb_t cb = (pa_source_output_info_cb_t) o->callback;
cb(o->context, NULL, eol, o->userdata);
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
-
+
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
t = pa_tagstruct_command(c, PA_COMMAND_GET_SOURCE_OUTPUT_INFO, &tag);
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
-
+
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_VOLUME, &tag);
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
-
+
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_MUTE, &tag);
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY_RETURN_NULL(c, idx != PA_INVALID_INDEX, PA_ERR_INVALID);
PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
-
+
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
t = pa_tagstruct_command(c, PA_COMMAND_SET_SINK_INPUT_VOLUME, &tag);
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY_RETURN_NULL(c, pa_cvolume_valid(volume), PA_ERR_INVALID);
PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
-
+
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_VOLUME, &tag);
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY_RETURN_NULL(c, !name || *name, PA_ERR_INVALID);
-
+
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
t = pa_tagstruct_command(c, PA_COMMAND_SET_SOURCE_MUTE, &tag);
if (!o->context)
goto finish;
-
+
if (command != PA_COMMAND_REPLY) {
if (pa_context_handle_error(o->context, command, t) < 0)
goto finish;
eol = -1;
} else {
-
+
while (!pa_tagstruct_eof(t)) {
pa_sample_info i;
-
+
if (pa_tagstruct_getu32(t, &i.index) < 0 ||
pa_tagstruct_gets(t, &i.name) < 0 ||
pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
pa_tagstruct_getu32(t, &i.bytes) < 0 ||
pa_tagstruct_get_boolean(t, &i.lazy) < 0 ||
pa_tagstruct_gets(t, &i.filename) < 0) {
-
+
pa_context_fail(o->context, PA_ERR_PROTOCOL);
goto finish;
}
}
}
}
-
+
if (o->callback) {
pa_sample_info_cb_t cb = (pa_sample_info_cb_t) o->callback;
cb(o->context, NULL, eol, o->userdata);
pa_tagstruct *t;
pa_operation *o;
uint32_t tag;
-
+
assert(c);
assert(c->ref >= 1);
assert(cb);
pa_operation* pa_context_kill_client(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) {
return command_kill(c, PA_COMMAND_KILL_CLIENT, idx, cb, userdata);
}
-
+
pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata) {
return command_kill(c, PA_COMMAND_KILL_SINK_INPUT, idx, cb, userdata);
}
if (!o->context)
goto finish;
-
+
if (command != PA_COMMAND_REPLY) {
if (pa_context_handle_error(o->context, command, t) < 0)
goto finish;
pa_operation *o;
pa_tagstruct *t;
uint32_t tag;
-
+
assert(c);
assert(c->ref >= 1);
eol = -1;
} else {
-
+
while (!pa_tagstruct_eof(t)) {
pa_autoload_info i;
-
+
if (pa_tagstruct_getu32(t, &i.index) < 0 ||
pa_tagstruct_gets(t, &i.name) < 0 ||
pa_tagstruct_getu32(t, &i.type) < 0 ||
}
}
}
-
+
if (o->callback) {
pa_autoload_info_cb_t cb = (pa_autoload_info_cb_t) o->callback;
cb(o->context, NULL, eol, o->userdata);
pa_tagstruct *t;
pa_operation *o;
uint32_t tag;
-
+
assert(c);
assert(c->ref >= 1);
assert(cb);
assert(c);
assert(c->ref >= 1);
-
+
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
PA_CHECK_VALIDITY_RETURN_NULL(c, type == PA_AUTOLOAD_SINK || type == PA_AUTOLOAD_SOURCE, PA_ERR_INVALID);
assert(c);
assert(c->ref >= 1);
-
+
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
PA_CHECK_VALIDITY_RETURN_NULL(c, type == PA_AUTOLOAD_SINK || type == PA_AUTOLOAD_SOURCE, PA_ERR_INVALID);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/** Stores information about sinks */
typedef struct pa_sink_info {
const char *name; /**< Name of the sink */
- uint32_t index; /**< Index of the sink */
+ uint32_t index; /**< Index of the sink */
const char *description; /**< Description of this sink */
pa_sample_spec sample_spec; /**< Sample spec of this sink */
pa_channel_map channel_map; /**< Channel map \since 0.8 */
pa_operation* pa_context_get_sink_info_list(pa_context *c, pa_sink_info_cb_t cb, void *userdata);
/** Stores information about sources */
-typedef struct pa_source_info {
+typedef struct pa_source_info {
const char *name ; /**< Name of the source */
uint32_t index; /**< Index of the source */
const char *description; /**< Description of this source */
/** Stores information about sink inputs */
typedef struct pa_sink_input_info {
- uint32_t index; /**< Index of the sink input */
+ uint32_t index; /**< Index of the sink input */
const char *name; /**< Name of the sink input */
uint32_t owner_module; /**< Index of the module this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any module */
uint32_t client; /**< Index of the client this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any client */
/** Stores information about source outputs */
typedef struct pa_source_output_info {
- uint32_t index; /**< Index of the sink input */
+ uint32_t index; /**< Index of the sink input */
const char *name; /**< Name of the sink input */
- uint32_t owner_module; /**< Index of the module this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any module */
- uint32_t client; /**< Index of the client this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any client */
- uint32_t source; /**< Index of the connected source */
+ uint32_t owner_module; /**< Index of the module this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any module */
+ uint32_t client; /**< Index of the client this sink input belongs to, or PA_INVALID_INDEX when it does not belong to any client */
+ uint32_t source; /**< Index of the connected source */
pa_sample_spec sample_spec; /**< The sample specification of the source output */
pa_channel_map channel_map; /**< Channel map */
pa_usec_t buffer_usec; /**< Latency due to buffering in the source output, see pa_latency_info for details. \since 0.5 */
uint32_t memblock_total_size; /**< Currentl total size of allocated memory blocks */
uint32_t memblock_allocated; /**< Allocated memory blocks during the whole lifetime of the daemon */
uint32_t memblock_allocated_size; /**< Total size of all memory blocks allocated during the whole lifetime of the daemon */
- uint32_t scache_size; /**< Total size of all sample cache entries. \since 0.4 */
+ uint32_t scache_size; /**< Total size of all sample cache entries. \since 0.4 */
} pa_stat_info;
/** Callback prototype for pa_context_stat() */
/** Kill a client. \since 0.5 */
pa_operation* pa_context_kill_client(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
-
+
/** Kill a sink input. \since 0.5 */
pa_operation* pa_context_kill_sink_input(pa_context *c, uint32_t idx, pa_context_success_cb_t cb, void *userdata);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
#include <pulse/cdecl.h>
/** \file
- *
+ *
* Main loop abstraction layer. Both the PulseAudio core and the
* PulseAudio client library use a main loop abstraction layer. Due to
* this it is possible to embed PulseAudio into other
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
static void dispatch(pa_mainloop_api*a, int sig) {
pa_signal_event*s;
- for (s = signals; s; s = s->next)
+ for (s = signals; s; s = s->next)
if (s->sig == sig) {
assert(s->callback);
s->callback(a, s, sig, s->userdata);
pa_log("read(): %s", pa_cstrerror(errno));
return;
}
-
+
if (r != sizeof(sig)) {
pa_log("short read()");
return;
while (signals)
pa_signal_free(signals);
-
+
api->io_free(io_event);
io_event = NULL;
#endif
assert(sig > 0 && _callback);
-
+
for (e = signals; e; e = e->next)
if (e->sig == sig)
goto fail;
-
+
e = pa_xmalloc(sizeof(pa_signal_event));
e->sig = sig;
e->callback = _callback;
sa.sa_handler = signal_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
-
+
if (sigaction(sig, &sa, &e->saved_sigaction) < 0)
#else
if ((e->saved_handler = signal(sig, signal_handler)) == SIG_ERR)
if (e->destroy_callback)
e->destroy_callback(api, e, e->userdata);
-
+
pa_xfree(e);
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
struct pa_io_event {
pa_mainloop *mainloop;
int dead;
-
+
int fd;
pa_io_event_flags_t events;
struct pollfd *pollfd;
-
+
pa_io_event_cb_t callback;
void *userdata;
pa_io_event_destroy_cb_t destroy_callback;
pa_io_event_flags_t events,
pa_io_event_cb_t callback,
void *userdata) {
-
+
pa_mainloop *m;
pa_io_event *e;
assert(a->userdata);
assert(fd >= 0);
assert(callback);
-
+
m = a->userdata;
assert(a == &m->api);
e->fd = fd;
e->events = events;
e->pollfd = NULL;
-
+
e->callback = callback;
e->userdata = userdata;
e->destroy_callback = NULL;
if (e->events == events)
return;
-
+
e->events = events;
if (e->pollfd)
static void mainloop_io_set_destroy(pa_io_event *e, pa_io_event_destroy_cb_t callback) {
assert(e);
-
+
e->destroy_callback = callback;
}
assert(a);
assert(a->userdata);
assert(callback);
-
+
m = a->userdata;
assert(a == &m->api);
e->enabled = 1;
m->n_enabled_defer_events++;
-
+
e->callback = callback;
e->userdata = userdata;
e->destroy_callback = NULL;
e->mainloop->n_enabled_defer_events++;
pa_mainloop_wakeup(e->mainloop);
}
-
+
e->enabled = b;
}
const struct timeval *tv,
pa_time_event_cb_t callback,
void *userdata) {
-
+
pa_mainloop *m;
pa_time_event *e;
assert(a);
assert(a->userdata);
assert(callback);
-
+
m = a->userdata;
assert(a == &m->api);
if (e->enabled)
pa_mainloop_wakeup(m);
-
+
return e;
}
if (e->mainloop->cached_next_time_event && e->enabled) {
assert(e->mainloop->cached_next_time_event->enabled);
-
+
if (pa_timeval_cmp(tv, &e->mainloop->cached_next_time_event->timeval) < 0)
e->mainloop->cached_next_time_event = e;
} else if (e->mainloop->cached_next_time_event == e)
if (e->mainloop->cached_next_time_event == e)
e->mainloop->cached_next_time_event = NULL;
-
+
/* no wakeup needed here. Think about it! */
}
static void mainloop_quit(pa_mainloop_api*a, int retval) {
pa_mainloop *m;
-
+
assert(a);
assert(a->userdata);
m = a->userdata;
pa_mainloop_quit(m, retval);
}
-
+
static const pa_mainloop_api vtable = {
.userdata = NULL,
.time_restart = mainloop_time_restart,
.time_free = mainloop_time_free,
.time_set_destroy = mainloop_time_set_destroy,
-
+
.defer_new = mainloop_defer_new,
.defer_enable = mainloop_defer_enable,
.defer_free = mainloop_defer_free,
.defer_set_destroy = mainloop_defer_set_destroy,
-
+
.quit = mainloop_quit,
};
m->cached_next_time_event = NULL;
m->prepared_timeout = 0;
-
+
m->pollfds = NULL;
m->max_pollfds = m->n_pollfds = 0;
m->rebuild_pollfds = 1;
m->poll_func = NULL;
m->poll_func_userdata = NULL;
m->poll_func_ret = -1;
-
+
return m;
}
if (!force && m->io_events_please_scan <= 0)
break;
-
+
if (force || e->dead) {
PA_LLIST_REMOVE(pa_io_event, m->io_events, e);
assert(m->io_events_please_scan > 0);
m->io_events_please_scan--;
}
-
+
if (e->destroy_callback)
e->destroy_callback(&m->api, e, e->userdata);
-
+
pa_xfree(e);
m->rebuild_pollfds = 1;
if (!force && m->time_events_please_scan <= 0)
break;
-
+
if (force || e->dead) {
PA_LLIST_REMOVE(pa_time_event, m->time_events, e);
assert(m->n_enabled_time_events > 0);
m->n_enabled_time_events--;
}
-
+
if (e->destroy_callback)
e->destroy_callback(&m->api, e, e->userdata);
-
+
pa_xfree(e);
}
if (!force && m->defer_events_please_scan <= 0)
break;
-
+
if (force || e->dead) {
PA_LLIST_REMOVE(pa_defer_event, m->defer_events, e);
assert(m->n_enabled_defer_events > 0);
m->n_enabled_defer_events--;
}
-
+
if (e->destroy_callback)
e->destroy_callback(&m->api, e, e->userdata);
-
+
pa_xfree(e);
}
int r = 0, k;
assert(m->poll_func_ret > 0);
-
+
for (e = m->io_events, k = m->poll_func_ret; e && !m->quit && k > 0; e = e->next) {
if (e->dead || !e->pollfd || !e->pollfd->revents)
continue;
-
+
assert(e->pollfd->fd == e->fd && e->callback);
e->callback(&m->api, e, e->fd, map_flags_from_libc(e->pollfd->revents), e->userdata);
e->pollfd->revents = 0;
for (e = m->defer_events; e && !m->quit; e = e->next) {
if (e->dead || !e->enabled)
continue;
-
+
assert(e->callback);
e->callback(&m->api, e, e->userdata);
r++;
if (m->cached_next_time_event)
return m->cached_next_time_event;
-
+
for (t = m->time_events; t; t = t->next) {
if (t->dead || !t->enabled)
if (t->timeval.tv_sec <= 0)
return 0;
-
+
pa_gettimeofday(&now);
if (pa_timeval_cmp(&t->timeval, &now) <= 0)
pa_gettimeofday(&now);
for (e = m->time_events; e && !m->quit; e = e->next) {
-
+
if (e->dead || !e->enabled)
continue;
if (m->n_enabled_defer_events <= 0) {
if (m->rebuild_pollfds)
rebuild_pollfds(m);
-
+
m->prepared_timeout = calc_next_timeout(m);
if (timeout >= 0 && (timeout < m->prepared_timeout || m->prepared_timeout < 0))
m->prepared_timeout = timeout;
m->poll_func_ret = 0;
else {
assert(!m->rebuild_pollfds);
-
+
if (m->poll_func)
m->poll_func_ret = m->poll_func(m->pollfds, m->n_pollfds, m->prepared_timeout, m->poll_func_userdata);
else
if (m->quit)
goto quit;
-
+
if (m->n_enabled_defer_events)
dispatched += dispatch_defer(m);
else {
- if (m->n_enabled_time_events)
+ if (m->n_enabled_time_events)
dispatched += dispatch_timeout(m);
-
+
if (m->quit)
goto quit;
if (m->poll_func_ret > 0)
dispatched += dispatch_pollfds(m);
}
-
+
if (m->quit)
goto quit;
-
+
m->state = STATE_PASSIVE;
return dispatched;
return r;
quit:
-
+
if ((r == -2) && retval)
*retval = pa_mainloop_get_retval(m);
return r;
int pa_mainloop_run(pa_mainloop *m, int *retval) {
int r;
-
+
while ((r = pa_mainloop_iterate(m, 1, retval)) >= 0);
if (r == -2)
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
*/
/** \file
- *
+ *
* A minimal main loop implementation based on the C library's poll()
* function. Using the routines defined herein you may create a simple
* main loop supporting the generic main loop abstraction layer as
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/* Refcounting is strictly one-way: from the "bigger" to the "smaller" object. */
PA_LLIST_PREPEND(pa_operation, c->operations, o);
pa_operation_ref(o);
-
+
return o;
}
pa_operation *pa_operation_ref(pa_operation *o) {
assert(o);
assert(o->ref >= 1);
-
+
o->ref++;
return o;
}
o->state = st;
if ((o->state == PA_OPERATION_DONE) || (o->state == PA_OPERATION_CANCELED)) {
-
+
if (o->context) {
assert(o->ref >= 2);
-
+
PA_LLIST_REMOVE(pa_operation, o->context->operations, o);
pa_operation_unref(o);
}
-
+
o->context = NULL;
o->stream = NULL;
o->callback = NULL;
void pa_operation_cancel(pa_operation *o) {
assert(o);
assert(o->ref >= 1);
-
+
operation_set_state(o, PA_OPERATION_CANCELED);
}
void pa_operation_done(pa_operation *o) {
assert(o);
assert(o->ref >= 1);
-
+
operation_set_state(o, PA_OPERATION_DONE);
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/** \mainpage
*
* \section intro_sec Introduction
- *
+ *
* This document describes the client API for the PulseAudio sound
* server. The API comes in two flavours to accomodate different styles
* of applications and different needs in complexity:
- *
+ *
* \li The complete but somewhat complicated to use asynchronous API
* \li The simplified, easy to use, but limited synchronous API
*
* locale. Some functions will filter invalid sequences from the string, some
* will simply fail. To ensure reliable behaviour, make sure everything you
* pass to the API is already in UTF-8.
-
+
* \section simple_sec Simple API
*
* Use this if you develop your program in synchronous style and just
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) {
assert(spec);
- return (size_t) (((double) t * spec->rate / 1000000))*pa_frame_size(spec);
+ return (size_t) (((double) t * spec->rate / 1000000))*pa_frame_size(spec);
}
int pa_sample_spec_valid(const pa_sample_spec *spec) {
char *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) {
assert(s && l && spec);
-
+
if (!pa_sample_spec_valid(spec))
snprintf(s, l, "Invalid");
else
}
pa_sample_format_t pa_parse_sample_format(const char *format) {
-
+
if (strcasecmp(format, "s16le") == 0)
return PA_SAMPLE_S16LE;
else if (strcasecmp(format, "s16be") == 0)
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
int pa_stream_connect_upload(pa_stream *s, size_t length) {
pa_tagstruct *t;
uint32_t tag;
-
+
assert(s);
PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY(s->context, length > 0, PA_ERR_INVALID);
-
+
pa_stream_ref(s);
-
+
s->direction = PA_STREAM_UPLOAD;
t = pa_tagstruct_command(s->context, PA_COMMAND_CREATE_UPLOAD_STREAM, &tag);
pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s, NULL);
pa_stream_set_state(s, PA_STREAM_CREATING);
-
+
pa_stream_unref(s);
return 0;
}
assert(c);
assert(c->ref >= 1);
-
+
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
PA_CHECK_VALIDITY_RETURN_NULL(c, !dev || *dev, PA_ERR_INVALID);
-
+
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
if (!dev)
dev = c->conf->default_sink;
-
+
t = pa_tagstruct_command(c, PA_COMMAND_PLAY_SAMPLE, &tag);
pa_tagstruct_putu32(t, PA_INVALID_INDEX);
pa_tagstruct_puts(t, dev);
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
-
+
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
-
+
t = pa_tagstruct_command(c, PA_COMMAND_REMOVE_SAMPLE, &tag);
pa_tagstruct_puts(t, name);
pa_pstream_send_tagstruct(c->pstream, t);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
goto label; \
} \
} while(0);
-
+
#define CHECK_DEAD_GOTO(p, rerror, label) do { \
if (!(p)->context || pa_context_get_state((p)->context) != PA_CONTEXT_READY || \
!(p)->stream || pa_stream_get_state((p)->stream) != PA_STREAM_READY) { \
const pa_channel_map *map,
const pa_buffer_attr *attr,
int *rerror) {
-
+
pa_simple *p;
int error = PA_ERR_INTERNAL, r;
if (!(p->mainloop = pa_threaded_mainloop_new()))
goto fail;
-
+
if (!(p->context = pa_context_new(pa_threaded_mainloop_get_api(p->mainloop), name)))
goto fail;
pa_context_set_state_callback(p->context, context_state_cb, p);
-
+
if (pa_context_connect(p->context, server, 0, NULL) < 0) {
error = pa_context_errno(p->context);
goto fail;
/* Wait until the context is ready */
pa_threaded_mainloop_wait(p->mainloop);
-
+
if (pa_context_get_state(p->context) != PA_CONTEXT_READY) {
error = pa_context_errno(p->context);
goto unlock_and_fail;
}
pa_threaded_mainloop_unlock(p->mainloop);
-
+
return p;
unlock_and_fail:
pa_threaded_mainloop_unlock(p->mainloop);
-
+
fail:
if (rerror)
*rerror = error;
if (s->mainloop)
pa_threaded_mainloop_stop(s->mainloop);
-
+
if (s->stream)
pa_stream_unref(s->stream);
-
+
if (s->context)
pa_context_unref(s->context);
int pa_simple_write(pa_simple *p, const void*data, size_t length, int *rerror) {
assert(p);
-
+
CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
CHECK_VALIDITY_RETURN_ANY(rerror, data && length, PA_ERR_INVALID, -1);
pa_threaded_mainloop_lock(p->mainloop);
-
+
CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
while (length > 0) {
size_t l;
int r;
-
+
while (!(l = pa_stream_writable_size(p->stream))) {
pa_threaded_mainloop_wait(p->mainloop);
CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
}
CHECK_SUCCESS_GOTO(p, rerror, l != (size_t) -1, unlock_and_fail);
-
+
if (l > length)
l = length;
r = pa_stream_write(p->stream, data, l, NULL, 0, PA_SEEK_RELATIVE);
CHECK_SUCCESS_GOTO(p, rerror, r >= 0, unlock_and_fail);
-
+
data = (const uint8_t*) data + l;
length -= l;
}
pa_threaded_mainloop_unlock(p->mainloop);
return 0;
-
+
unlock_and_fail:
pa_threaded_mainloop_unlock(p->mainloop);
return -1;
CHECK_VALIDITY_RETURN_ANY(rerror, data && length, PA_ERR_INVALID, -1);
pa_threaded_mainloop_lock(p->mainloop);
-
+
CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
while (length > 0) {
size_t l;
-
+
while (!p->read_data) {
int r;
-
+
r = pa_stream_peek(p->stream, &p->read_data, &p->read_length);
CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail);
} else
p->read_index = 0;
}
-
+
l = p->read_length < length ? p->read_length : length;
memcpy(data, (const uint8_t*) p->read_data+p->read_index, l);
data = (uint8_t*) data + l;
length -= l;
-
+
p->read_index += l;
p->read_length -= l;
if (!p->read_length) {
int r;
-
+
r = pa_stream_drop(p->stream);
p->read_data = NULL;
p->read_length = 0;
p->read_index = 0;
-
+
CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail);
}
}
pa_threaded_mainloop_unlock(p->mainloop);
return 0;
-
+
unlock_and_fail:
pa_threaded_mainloop_unlock(p->mainloop);
return -1;
int pa_simple_drain(pa_simple *p, int *rerror) {
pa_operation *o = NULL;
-
+
assert(p);
CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
}
CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail);
-
+
pa_operation_unref(o);
pa_threaded_mainloop_unlock(p->mainloop);
int pa_simple_flush(pa_simple *p, int *rerror) {
pa_operation *o = NULL;
-
+
assert(p);
CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
o = pa_stream_flush(p->stream, success_cb, p);
CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail);
-
+
p->operation_success = 0;
while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
pa_threaded_mainloop_wait(p->mainloop);
pa_usec_t pa_simple_get_latency(pa_simple *p, int *rerror) {
pa_usec_t t;
int negative;
-
+
assert(p);
-
+
pa_threaded_mainloop_lock(p->mainloop);
for (;;) {
CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
-
+
if (pa_stream_get_latency(p->stream, &t, &negative) >= 0)
break;
/* Wait until latency data is available again */
pa_threaded_mainloop_wait(p->mainloop);
}
-
+
pa_threaded_mainloop_unlock(p->mainloop);
return negative ? 0 : t;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map) {
pa_stream *s;
int i;
-
+
assert(c);
PA_CHECK_VALIDITY_RETURN_NULL(c, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID);
s->channel_map = *map;
else
pa_channel_map_init_auto(&s->channel_map, ss->channels, PA_CHANNEL_MAP_DEFAULT);
-
+
s->channel = 0;
s->channel_valid = 0;
s->syncid = c->csyncid++;
for (i = 0; i < PA_MAX_WRITE_INDEX_CORRECTIONS; i++)
s->write_index_corrections[i].valid = 0;
s->current_write_index_correction = 0;
-
+
s->corked = 0;
s->cached_time_valid = 0;
-
+
s->auto_timing_update_event = NULL;
s->auto_timing_update_requested = 0;
pa_stream* pa_stream_ref(pa_stream *s) {
assert(s);
assert(s->ref >= 1);
-
+
s->ref++;
return s;
}
pa_stream_state_t pa_stream_get_state(pa_stream *s) {
assert(s);
assert(s->ref >= 1);
-
+
return s->state;
}
pa_context* pa_stream_get_context(pa_stream *s) {
assert(s);
assert(s->ref >= 1);
-
+
return s->context;
}
assert(s->ref >= 1);
PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, PA_INVALID_INDEX);
-
+
return s->device_index;
}
-
+
void pa_stream_set_state(pa_stream *s, pa_stream_state_t st) {
assert(s);
assert(s->ref >= 1);
if (s->state == st)
return;
-
+
pa_stream_ref(s);
s->state = st;
/* Unref all operatio object that point to us */
for (o = s->context->operations; o; o = n) {
n = o->next;
-
+
if (o->stream == s)
pa_operation_cancel(o);
}
-
+
/* Drop all outstanding replies for this stream */
if (s->context->pdispatch)
pa_pdispatch_unregister_reply(s->context->pdispatch, s);
if (s->channel_valid)
pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL);
-
+
PA_LLIST_REMOVE(pa_stream, s->context->streams, s);
pa_stream_unref(s);
s->channel = 0;
s->channel_valid = 0;
-
+
s->context = NULL;
}
pa_context *c = userdata;
pa_stream *s;
uint32_t channel;
-
+
assert(pd);
assert(command == PA_COMMAND_PLAYBACK_STREAM_KILLED || command == PA_COMMAND_RECORD_STREAM_KILLED);
assert(t);
assert(c);
pa_context_ref(c);
-
+
if (pa_tagstruct_getu32(t, &channel) < 0 ||
!pa_tagstruct_eof(t)) {
pa_context_fail(c, PA_ERR_PROTOCOL);
goto finish;
}
-
+
if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel)))
goto finish;
pa_stream *s;
pa_context *c = userdata;
uint32_t bytes, channel;
-
+
assert(pd);
assert(command == PA_COMMAND_REQUEST);
assert(t);
assert(c);
pa_context_ref(c);
-
+
if (pa_tagstruct_getu32(t, &channel) < 0 ||
pa_tagstruct_getu32(t, &bytes) < 0 ||
!pa_tagstruct_eof(t)) {
pa_context_fail(c, PA_ERR_PROTOCOL);
goto finish;
}
-
+
if (!(s = pa_dynarray_get(c->playback_streams, channel)))
goto finish;
if (s->state == PA_STREAM_READY) {
s->requested_bytes += bytes;
-
+
if (s->requested_bytes > 0 && s->write_callback)
s->write_callback(s, s->requested_bytes, s->write_userdata);
}
assert(c);
pa_context_ref(c);
-
+
if (pa_tagstruct_getu32(t, &channel) < 0 ||
!pa_tagstruct_eof(t)) {
pa_context_fail(c, PA_ERR_PROTOCOL);
goto finish;
}
-
+
if (!(s = pa_dynarray_get(c->playback_streams, channel)))
goto finish;
if (!(s->flags & PA_STREAM_AUTO_TIMING_UPDATE))
return;
-
+
if (s->state == PA_STREAM_READY &&
(force || !s->auto_timing_update_requested)) {
pa_operation *o;
-
+
/* pa_log("automatically requesting new timing data"); */
if ((o = pa_stream_update_timing_info(s, NULL, NULL))) {
assert(s);
/* pa_log("invalidate r:%u w:%u tag:%u", r, w, s->context->ctag); */
-
+
if (s->state != PA_STREAM_READY)
return;
if (w) {
s->write_index_not_before = s->context->ctag;
-
+
if (s->timing_info_valid)
s->timing_info.write_index_corrupt = 1;
-
+
/* pa_log("write_index invalidated"); */
}
-
+
if (r) {
s->read_index_not_before = s->context->ctag;
-
+
if (s->timing_info_valid)
s->timing_info.read_index_corrupt = 1;
-
+
/* pa_log("read_index invalidated"); */
}
-
+
if ((s->direction == PA_STREAM_PLAYBACK && r) ||
(s->direction == PA_STREAM_RECORD && w))
s->cached_time_valid = 0;
-
+
request_auto_timing_update(s, 1);
}
void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
pa_stream *s = userdata;
-
+
assert(pd);
assert(s);
assert(s->state == PA_STREAM_CREATING);
-
+
pa_stream_ref(s);
-
+
if (command != PA_COMMAND_REPLY) {
if (pa_context_handle_error(s->context, command, t) < 0)
goto finish;
-
+
pa_stream_set_state(s, PA_STREAM_FAILED);
goto finish;
}
if (s->direction == PA_STREAM_RECORD) {
assert(!s->record_memblockq);
-
+
s->record_memblockq = pa_memblockq_new(
- 0,
+ 0,
s->buffer_attr.maxlength,
0,
pa_frame_size(&s->sample_spec),
pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s);
pa_stream_set_state(s, PA_STREAM_READY);
-
+
if (s->direction != PA_STREAM_UPLOAD &&
s->flags & PA_STREAM_AUTO_TIMING_UPDATE) {
struct timeval tv;
pa_stream_flags_t flags,
const pa_cvolume *volume,
pa_stream *sync_stream) {
-
+
pa_tagstruct *t;
uint32_t tag;
-
+
assert(s);
assert(s->ref >= 1);
-
+
PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY(s->context, !(flags & ~((direction != PA_STREAM_UPLOAD ?
PA_STREAM_START_CORKED|
s->direction = direction;
s->flags = flags;
-
+
if (sync_stream)
s->syncid = sync_stream->syncid;
-
+
if (attr)
s->buffer_attr = *attr;
else {
s->context,
s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_CREATE_PLAYBACK_STREAM : PA_COMMAND_CREATE_RECORD_STREAM,
&tag);
-
+
pa_tagstruct_put(
t,
PA_TAG_STRING, s->name,
PA_TAG_U32, s->buffer_attr.maxlength,
PA_TAG_BOOLEAN, !!(flags & PA_STREAM_START_CORKED),
PA_TAG_INVALID);
-
+
if (s->direction == PA_STREAM_PLAYBACK) {
pa_cvolume cv;
if (!volume)
volume = pa_cvolume_reset(&cv, s->sample_spec.channels);
-
+
pa_tagstruct_put_cvolume(t, volume);
} else
pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s, NULL);
pa_stream_set_state(s, PA_STREAM_CREATING);
-
+
pa_stream_unref(s);
return 0;
}
pa_stream_flags_t flags,
pa_cvolume *volume,
pa_stream *sync_stream) {
-
+
assert(s);
assert(s->ref >= 1);
-
+
return create_stream(PA_STREAM_PLAYBACK, s, dev, attr, flags, volume, sync_stream);
}
const char *dev,
const pa_buffer_attr *attr,
pa_stream_flags_t flags) {
-
+
assert(s);
assert(s->ref >= 1);
void (*free_cb)(void *p),
int64_t offset,
pa_seek_mode_t seek) {
-
+
pa_memchunk chunk;
-
+
assert(s);
assert(s->ref >= 1);
assert(data);
if (length <= 0)
return 0;
- if (free_cb)
+ if (free_cb)
chunk.memblock = pa_memblock_new_user(s->context->mempool, (void*) data, length, free_cb, 1);
else {
chunk.memblock = pa_memblock_new(s->context->mempool, length);
memcpy(chunk.memblock->data, data, length);
}
-
+
chunk.index = 0;
chunk.length = length;
pa_pstream_send_memblock(s->context->pstream, s->channel, offset, seek, &chunk);
pa_memblock_unref(chunk.memblock);
-
+
if (length < s->requested_bytes)
s->requested_bytes -= length;
else
s->requested_bytes = 0;
if (s->direction == PA_STREAM_PLAYBACK) {
-
+
/* Update latency request correction */
if (s->write_index_corrections[s->current_write_index_correction].valid) {
-
+
if (seek == PA_SEEK_ABSOLUTE) {
s->write_index_corrections[s->current_write_index_correction].corrupt = 0;
s->write_index_corrections[s->current_write_index_correction].absolute = 1;
} else
s->write_index_corrections[s->current_write_index_correction].corrupt = 1;
}
-
+
/* Update the write index in the already available latency data */
if (s->timing_info_valid) {
-
+
if (seek == PA_SEEK_ABSOLUTE) {
s->timing_info.write_index_corrupt = 0;
s->timing_info.write_index = offset + length;
if (!s->timing_info_valid || s->timing_info.write_index_corrupt)
request_auto_timing_update(s, 1);
}
-
+
return 0;
}
PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE);
-
+
if (!s->peek_memchunk.memblock) {
if (pa_memblockq_peek(s->record_memblockq, &s->peek_memchunk) < 0) {
PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY(s->context, s->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY(s->context, s->peek_memchunk.memblock, PA_ERR_BADSTATE);
-
+
pa_memblockq_drop(s->record_memblockq, &s->peek_memchunk, s->peek_memchunk.length);
/* Fix the simulated local read index */
if (s->timing_info_valid && !s->timing_info.read_index_corrupt)
s->timing_info.read_index += s->peek_memchunk.length;
-
+
pa_memblock_unref(s->peek_memchunk.memblock);
s->peek_memchunk.length = 0;
s->peek_memchunk.index = 0;
PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE, (size_t) -1);
PA_CHECK_VALIDITY_RETURN_ANY(s->context, s->direction != PA_STREAM_RECORD, PA_ERR_BADSTATE, (size_t) -1);
-
+
return s->requested_bytes;
}
pa_operation *o;
pa_tagstruct *t;
uint32_t tag;
-
+
assert(s);
assert(s->ref >= 1);
pa_operation *o = userdata;
struct timeval local, remote, now;
pa_timing_info *i;
-
+
assert(pd);
assert(o);
i = &o->stream->timing_info;
/* pa_log("pre corrupt w:%u r:%u\n", !o->stream->timing_info_valid || i->write_index_corrupt,!o->stream->timing_info_valid || i->read_index_corrupt); */
-
+
o->stream->timing_info_valid = 0;
i->write_index_corrupt = 0;
i->read_index_corrupt = 0;
!pa_tagstruct_eof(t)) {
pa_context_fail(o->context, PA_ERR_PROTOCOL);
goto finish;
-
+
} else {
o->stream->timing_info_valid = 1;
pa_gettimeofday(&now);
-
+
/* Calculcate timestamps */
if (pa_timeval_cmp(&local, &remote) <= 0 && pa_timeval_cmp(&remote, &now) <= 0) {
/* local and remote seem to have synchronized clocks */
-
+
if (o->stream->direction == PA_STREAM_PLAYBACK)
i->transport_usec = pa_timeval_diff(&remote, &local);
else
i->transport_usec = pa_timeval_diff(&now, &remote);
-
+
i->synchronized_clocks = 1;
i->timestamp = remote;
} else {
uint32_t ctag = tag;
/* Go through the saved correction values and add up the total correction.*/
-
+
for (n = 0, j = o->stream->current_write_index_correction+1;
n < PA_MAX_WRITE_INDEX_CORRECTIONS;
n++, j = (j + 1) % PA_MAX_WRITE_INDEX_CORRECTIONS) {
if (!i->read_index_corrupt)
i->read_index -= pa_memblockq_get_length(o->stream->record_memblockq);
}
-
+
o->stream->cached_time_valid = 0;
}
o->stream->auto_timing_update_requested = 0;
/* pa_log("post corrupt w:%u r:%u\n", i->write_index_corrupt || !o->stream->timing_info_valid, i->read_index_corrupt || !o->stream->timing_info_valid); */
-
+
/* Clear old correction entries */
if (o->stream->direction == PA_STREAM_PLAYBACK) {
int n;
-
+
for (n = 0; n < PA_MAX_WRITE_INDEX_CORRECTIONS; n++) {
if (!o->stream->write_index_corrections[n].valid)
continue;
-
+
if (o->stream->write_index_corrections[n].tag <= tag)
o->stream->write_index_corrections[n].valid = 0;
}
if (o->stream->latency_update_callback)
o->stream->latency_update_callback(o->stream, o->stream->latency_update_userdata);
-
+
if (o->callback && o->stream && o->stream->state == PA_STREAM_READY) {
pa_stream_success_cb_t cb = (pa_stream_success_cb_t) o->callback;
cb(o->stream, o->stream->timing_info_valid, o->userdata);
}
-
+
finish:
pa_operation_done(o);
pa_tagstruct *t;
struct timeval now;
int cidx = 0;
-
+
assert(s);
assert(s->ref >= 1);
PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
-
+
if (s->direction == PA_STREAM_PLAYBACK) {
/* Find a place to store the write_index correction data for this entry */
cidx = (s->current_write_index_correction + 1) % PA_MAX_WRITE_INDEX_CORRECTIONS;
-
+
/* Check if we could allocate a correction slot. If not, there are too many outstanding queries */
PA_CHECK_VALIDITY_RETURN_NULL(s->context, !s->write_index_corrections[cidx].valid, PA_ERR_INTERNAL);
}
o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);
-
+
t = pa_tagstruct_command(
s->context,
s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_GET_PLAYBACK_LATENCY : PA_COMMAND_GET_RECORD_LATENCY,
&tag);
pa_tagstruct_putu32(t, s->channel);
pa_tagstruct_put_timeval(t, pa_gettimeofday(&now));
-
+
pa_pstream_send_tagstruct(s->context->pstream, t);
pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, stream_get_timing_info_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
o->stream->write_index_corrections[cidx].value = 0;
o->stream->write_index_corrections[cidx].corrupt = 0;
}
-
+
/* pa_log("requesting update %u\n", tag); */
-
+
return o;
}
void pa_stream_disconnect_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
pa_stream *s = userdata;
-
+
assert(pd);
assert(s);
assert(s->ref >= 1);
int pa_stream_disconnect(pa_stream *s) {
pa_tagstruct *t;
uint32_t tag;
-
+
assert(s);
assert(s->ref >= 1);
void pa_stream_set_overflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) {
assert(s);
assert(s->ref >= 1);
-
+
s->overflow_callback = cb;
s->overflow_userdata = userdata;
}
void pa_stream_set_underflow_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) {
assert(s);
assert(s->ref >= 1);
-
+
s->underflow_callback = cb;
s->underflow_userdata = userdata;
}
void pa_stream_set_latency_update_callback(pa_stream *s, pa_stream_notify_cb_t cb, void *userdata) {
assert(s);
assert(s->ref >= 1);
-
+
s->latency_update_callback = cb;
s->latency_update_userdata = userdata;
}
void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
pa_operation *o = userdata;
int success = 1;
-
+
assert(pd);
assert(o);
assert(o->ref >= 1);
if (!o->context)
goto finish;
-
+
if (command != PA_COMMAND_REPLY) {
if (pa_context_handle_error(o->context, command, t) < 0)
goto finish;
pa_operation *o;
pa_tagstruct *t;
uint32_t tag;
-
+
assert(s);
assert(s->ref >= 1);
-
+
PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
s->corked = b;
-
+
o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);
t = pa_tagstruct_command(
pa_tagstruct *t;
pa_operation *o;
uint32_t tag;
-
+
assert(s);
assert(s->ref >= 1);
PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->state == PA_STREAM_READY, PA_ERR_BADSTATE);
-
+
o = pa_operation_new(s->context, s, (pa_operation_cb_t) cb, userdata);
t = pa_tagstruct_command(s->context, command, &tag);
pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) {
pa_operation *o;
-
+
PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction != PA_STREAM_UPLOAD, PA_ERR_BADSTATE);
-
+
if ((o = stream_send_simple_command(s, s->direction == PA_STREAM_PLAYBACK ? PA_COMMAND_FLUSH_PLAYBACK_STREAM : PA_COMMAND_FLUSH_RECORD_STREAM, cb, userdata))) {
if (s->direction == PA_STREAM_PLAYBACK) {
if (s->write_index_corrections[s->current_write_index_correction].valid)
s->write_index_corrections[s->current_write_index_correction].corrupt = 1;
-
+
if (s->timing_info_valid)
s->timing_info.write_index_corrupt = 1;
- if (s->buffer_attr.prebuf > 0)
+ if (s->buffer_attr.prebuf > 0)
invalidate_indexes(s, 1, 0);
else
request_auto_timing_update(s, 1);
} else
invalidate_indexes(s, 0, 1);
}
-
+
return o;
}
pa_operation* pa_stream_trigger(pa_stream *s, pa_stream_success_cb_t cb, void *userdata) {
pa_operation *o;
-
+
PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE);
PA_CHECK_VALIDITY_RETURN_NULL(s->context, s->buffer_attr.prebuf > 0, PA_ERR_BADSTATE);
if ((o = stream_send_simple_command(s, PA_COMMAND_TRIGGER_PLAYBACK_STREAM, cb, userdata)))
invalidate_indexes(s, 1, 0);
-
+
return o;
}
pa_operation *o;
pa_tagstruct *t;
uint32_t tag;
-
+
assert(s);
assert(s->ref >= 1);
assert(name);
* to us, we assume that the real output time is actually
* a little ahead */
usec += s->timing_info.transport_usec;
-
+
/* However, the output device usually maintains a buffer
too, hence the real sample currently played is a little
back */
else
usec -= s->timing_info.sink_usec;
}
-
+
} else if (s->direction == PA_STREAM_RECORD) {
/* The last byte written into the server side queue had
* this time value associated */
if (!s->corked) {
/* Add transport latency */
usec += s->timing_info.transport_usec;
-
+
/* Add latency of data in device buffer */
usec += s->timing_info.source_usec;
-
+
/* If this is a monitor source, we need to correct the
* time by the playback device buffer */
if (s->timing_info.sink_usec >= usec)
if (r_usec)
*r_usec = usec;
-
+
return 0;
}
static pa_usec_t time_counter_diff(pa_stream *s, pa_usec_t a, pa_usec_t b, int *negative) {
assert(s);
assert(s->ref >= 1);
-
+
if (negative)
*negative = 0;
- if (a >= b)
+ if (a >= b)
return a-b;
else {
if (negative && s->direction == PA_STREAM_RECORD) {
PA_CHECK_VALIDITY(s->context, s->timing_info_valid, PA_ERR_NODATA);
PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_PLAYBACK || !s->timing_info.write_index_corrupt, PA_ERR_NODATA);
PA_CHECK_VALIDITY(s->context, s->direction != PA_STREAM_RECORD || !s->timing_info.read_index_corrupt, PA_ERR_NODATA);
-
+
if ((r = pa_stream_get_time(s, &t)) < 0)
return r;
if (cindex < 0)
cindex = 0;
-
+
c = pa_bytes_to_usec(cindex, &s->sample_spec);
if (s->direction == PA_STREAM_PLAYBACK)
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* read index may be larger than the write index, in which case
* silence is played. If the application writes data to indexes lower
* than the read index, the data is immediately lost.
- *
+ *
* \section transfer_sec Transferring Data
*
* Once the stream is up, data can start flowing between the client and the
* \li PA_SEEK_ABSOLUTE - seek relative to the beginning of the playback buffer, (i.e. the first that was ever played in the stream)
* \li PA_SEEK_RELATIVE_ON_READ - seek relative to the current read index. Use this to write data to the output buffer that should be played as soon as possible
* \li PA_SEEK_RELATIVE_END - seek relative to the last byte ever written.
- *
+ *
* If an application just wants to append some data to the output
* buffer, PA_SEEK_RELATIVE and an offset of 0 should be used.
*
* After a call to pa_stream_write() the write index will be left at
* the position right after the last byte of the written data.
- *
+ *
* \section latency_sec Latency
*
* A major problem with networked audio is the increased latency caused by
* this option with PA_STREAM_AUTO_TIMING_UPDATE, which will enable
* you to monitor the current playback time/latency very precisely and
* very frequently without requiring a network round trip every time.
- *
+ *
* \section flow_sec Overflow and underflow
*
* Even with the best precautions, buffers will sometime over - or
/** Create a new, unconnected stream with the specified name and sample type */
pa_stream* pa_stream_new(
- pa_context *c /**< The context to create this stream in */,
+ pa_context *c /**< The context to create this stream in */,
const char *name /**< A name for this stream */,
const pa_sample_spec *ss /**< The desired sample format */,
const pa_channel_map *map /**< The desired channel map, or NULL for default */);
* is not copied. If NULL, the data is copied into an internal
* buffer. The client my freely seek around in the output buffer. For
* most applications passing 0 and PA_SEEK_RELATIVE as arguments for
- * offset and seek should be useful.*/
+ * offset and seek should be useful.*/
int pa_stream_write(
pa_stream *p /**< The stream to use */,
const void *data /**< The data to write */,
* data will point to the actual data and length will contain the size
* of the data in bytes (which can be less than a complete framgnet).
* Use pa_stream_drop() to actually remove the data from the
- * buffer. If no data is available will return a NULL pointer \since 0.8 */
+ * buffer. If no data is available will return a NULL pointer \since 0.8 */
int pa_stream_peek(
pa_stream *p /**< The stream to use */,
const void **data /**< Pointer to pointer that will point to data */,
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
assert(c->ref >= 1);
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
-
+
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
t = pa_tagstruct_command(c, PA_COMMAND_SUBSCRIBE, &tag);
void pa_context_set_subscribe_callback(pa_context *c, pa_context_subscribe_cb_t cb, void *userdata) {
assert(c);
assert(c->ref >= 1);
-
+
c->subscribe_callback = cb;
c->subscribe_userdata = userdata;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_mutex_free(m->mutex);
pa_cond_free(m->cond);
pa_cond_free(m->accept_cond);
-
+
pa_xfree(m);
}
void pa_threaded_mainloop_lock(pa_threaded_mainloop *m) {
assert(m);
-
+
/* Make sure that this function is not called from the helper thread */
assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m));
void pa_threaded_mainloop_unlock(pa_threaded_mainloop *m) {
assert(m);
-
+
/* Make sure that this function is not called from the helper thread */
assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m));
void pa_threaded_mainloop_wait(pa_threaded_mainloop *m) {
assert(m);
-
+
/* Make sure that this function is not called from the helper thread */
assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m));
void pa_threaded_mainloop_accept(pa_threaded_mainloop *m) {
assert(m);
-
+
/* Make sure that this function is not called from the helper thread */
assert(!m->thread || !pa_thread_is_running(m->thread) || !in_worker(m));
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* deal with that.
*
* The functions will not dead lock because the wait function will release
- * the lock before waiting and then regrab it once it has been signaled.
+ * the lock before waiting and then regrab it once it has been signaled.
* For those of you familiar with threads, the behaviour is that of a
* condition variable.
*
*/
/** \file
- *
+ *
* A thread based event loop implementation based on pa_mainloop. The
* event loop is run in a helper thread in the background. A few
* synchronization primitives are available to access the objects
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
struct timeval *pa_gettimeofday(struct timeval *tv) {
#ifdef HAVE_GETTIMEOFDAY
assert(tv);
-
+
return gettimeofday(tv, NULL) < 0 ? NULL : tv;
#elif defined(OS_IS_WIN32)
/*
pa_usec_t pa_timeval_age(const struct timeval *tv) {
struct timeval now;
assert(tv);
-
+
return pa_timeval_diff(pa_gettimeofday(&now), tv);
}
struct timeval* pa_timeval_add(struct timeval *tv, pa_usec_t v) {
unsigned long secs;
assert(tv);
-
+
secs = (v/1000000);
tv->tv_sec += (unsigned long) secs;
v -= secs*1000000;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
if (o)
o++;
-
+
continue;
error:
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
if (!(p = getenv("USER")) && !(p = getenv("LOGNAME")) && !(p = getenv("USERNAME"))) {
#ifdef HAVE_PWD_H
-
+
#ifdef HAVE_GETPWUID_R
if (getpwuid_r(getuid(), &pw, buf, sizeof(buf), &r) != 0 || !r) {
#else
snprintf(s, l, "%lu", (unsigned long) getuid());
return s;
}
-
+
p = r->pw_name;
#elif defined(OS_IS_WIN32) /* HAVE_PWD_H */
#if defined(OS_IS_WIN32)
{
char path[PATH_MAX];
-
+
if (GetModuleFileName(NULL, path, PATH_MAX))
return pa_strlcpy(s, pa_path_get_filename(path), l);
}
#endif
-
+
#ifdef HAVE_READLINK
{
int i;
char path[PATH_MAX];
/* This works on Linux only */
-
+
if ((i = readlink("/proc/self/exe", path, sizeof(path)-1)) >= 0) {
path[i] = 0;
return pa_strlcpy(s, pa_path_get_filename(path), l);
}
}
-
+
#endif
-
+
#if defined(HAVE_SYS_PRCTL_H) && defined(PR_GET_NAME)
{
char tcomm[TASK_COMM_LEN+1];
memset(tcomm, 0, sizeof(tcomm));
-
+
/* This works on Linux only */
if (prctl(PR_GET_NAME, (unsigned long) tcomm, 0, 0, 0) == 0)
return pa_strlcpy(s, tcomm, l);
-
+
}
#endif
-
+
return NULL;
}
char *pa_get_fqdn(char *s, size_t l) {
char hn[256];
-#ifdef HAVE_GETADDRINFO
+#ifdef HAVE_GETADDRINFO
struct addrinfo *a, hints;
#endif
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_flags = AI_CANONNAME;
-
+
if (getaddrinfo(hn, NULL, &hints, &a) < 0 || !a || !a->ai_canonname || !*a->ai_canonname)
return pa_strlcpy(s, hn, l);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
if (a->channels != b->channels)
return 0;
-
+
for (i = 0; i < a->channels; i++)
if (a->values[i] != b->values[i])
return 0;
pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v) {
int i;
-
+
assert(a);
assert(channels > 0);
assert(channels <= PA_CHANNELS_MAX);
unsigned channel;
int first = 1;
char *e;
-
+
assert(s);
assert(l > 0);
assert(c);
pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) {
unsigned i;
-
+
assert(dest);
assert(a);
assert(b);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
void *p;
assert(size > 0);
assert(size < MAX_ALLOC_SIZE);
-
+
if (!(p = malloc(size)))
oom();
-
+
return p;
}
void *p;
assert(size > 0);
assert(size < MAX_ALLOC_SIZE);
-
+
if (!(p = calloc(1, size)))
oom();
-
+
return p;
}
-
+
void *pa_xrealloc(void *ptr, size_t size) {
void *p;
assert(size > 0);
assert(size < MAX_ALLOC_SIZE);
-
+
if (!(p = realloc(ptr, size)))
oom();
return p;
char *pa_xstrndup(const char *s, size_t l) {
char *e, *r;
-
+
if (!s)
return NULL;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
static void dispatch_event(pa_anotify *a) {
assert(a);
assert(a->queue_index < a->n_queued_events);
-
+
a->callback(a->queued_events[a->queue_index++], a->userdata);
if (a->queue_index >= a->n_queued_events) {
int fd,
pa_io_event_flags_t events,
void *userdata) {
-
+
pa_anotify *a = userdata;
ssize_t r;
assert(a);
assert(events == PA_IO_EVENT_INPUT);
assert(a->n_queued_events == 0);
-
+
r = read(fd, a->queued_events, sizeof(a->queued_events));
assert(r > 0);
pa_anotify *pa_anotify_new(pa_mainloop_api*api, pa_anotify_cb_t cb, void *userdata) {
pa_anotify *a;
-
+
assert(api);
assert(cb);
pa_xfree(a);
return NULL;
}
-
+
a->api = api;
a->callback = cb;
a->userdata = userdata;
close(a->fds[0]);
if (a->fds[1] >= 0)
close(a->fds[1]);
-
+
pa_xfree(a);
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
int pa_authkey_prop_get(pa_core *c, const char *name, void *data, size_t len) {
struct authkey_data *a;
assert(c && name && data && len > 0);
-
+
if (!(a = pa_property_get(c, name)))
return -1;
memcpy(a+1, data, len);
pa_property_set(c, name, a);
-
+
return 0;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
if ((size_t) r != length) {
pa_log_debug("got %d bytes from cookie file '%s', expected %d", (int)r, fn, (int)length);
-
+
if (!writable) {
pa_log("unable to write cookie to read only file");
goto finish;
}
-
+
if (generate(fd, data, length) < 0)
goto finish;
}
ret = 0;
-
+
finish:
if (fd >= 0) {
-
+
if (unlock)
pa_lock_fd(fd, 0);
-
+
close(fd);
}
char homedir[PATH_MAX];
if (!pa_get_home_dir(homedir, sizeof(homedir)))
return NULL;
-
+
#ifndef OS_IS_WIN32
snprintf(s, l, "%s/%s", homedir, fn);
#else
if (!(p = normalize_path(fn, path, sizeof(path))))
return -2;
-
+
return pa_authkey_load(p, data, length);
}
}
ret = 0;
-
+
finish:
if (fd >= 0) {
-
+
if (unlock)
pa_lock_fd(fd, 0);
-
+
close(fd);
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
static pa_autoload_entry* entry_new(pa_core *c, const char *name) {
pa_autoload_entry *e = NULL;
assert(c && name);
-
+
if (c->autoload_hashmap && (e = pa_hashmap_get(c->autoload_hashmap, name)))
return NULL;
-
+
e = pa_xmalloc(sizeof(pa_autoload_entry));
e->core = c;
e->name = pa_xstrdup(name);
e->module = e->argument = NULL;
e->in_action = 0;
-
+
if (!c->autoload_hashmap)
c->autoload_hashmap = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
assert(c->autoload_hashmap);
-
+
pa_hashmap_put(c->autoload_hashmap, e->name, e);
if (!c->autoload_idxset)
pa_idxset_put(c->autoload_idxset, e, &e->index);
pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_AUTOLOAD|PA_SUBSCRIPTION_EVENT_NEW, e->index);
-
+
return e;
}
int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type_t type, const char*module, const char *argument, uint32_t *idx) {
pa_autoload_entry *e = NULL;
assert(c && name && module && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE));
-
+
if (!(e = entry_new(c, name)))
return -1;
-
+
e->module = pa_xstrdup(module);
e->argument = pa_xstrdup(argument);
e->type = type;
if (idx)
*idx = e->index;
-
+
return 0;
}
if ((m = pa_module_load(c, e->module, e->argument)))
m->auto_unload = 1;
}
-
+
e->in_action = 0;
}
pa_hashmap_free(c->autoload_hashmap, free_func, NULL);
c->autoload_hashmap = NULL;
}
-
+
if (c->autoload_idxset) {
pa_idxset_free(c->autoload_idxset, NULL, NULL);
c->autoload_idxset = NULL;
const pa_autoload_entry* pa_autoload_get_by_name(pa_core *c, const char*name, pa_namereg_type_t type) {
pa_autoload_entry *e;
assert(c && name);
-
+
if (!c->autoload_hashmap || !(e = pa_hashmap_get(c->autoload_hashmap, name)) || e->type != type)
return NULL;
const pa_autoload_entry* pa_autoload_get_by_index(pa_core *c, uint32_t idx) {
pa_autoload_entry *e;
assert(c && idx != PA_IDXSET_INVALID);
-
+
if (!c->autoload_idxset || !(e = pa_idxset_get_by_index(c->autoload_idxset, idx)))
return NULL;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
char *name;
pa_namereg_type_t type; /* Type of the autoload entry */
int in_action; /* Currently loaded */
- char *module, *argument;
+ char *module, *argument;
} pa_autoload_entry;
/* Add a new autoload entry of the given time, with the speicified
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
static void watch_callback(pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) {
AvahiWatch *w = userdata;
-
+
assert(a);
assert(e);
assert(w);
assert(api);
assert(fd >= 0);
assert(callback);
-
+
p = api->userdata;
assert(p);
return w;
}
-
+
static void watch_update(AvahiWatch *w, AvahiWatchEvent event) {
assert(w);
w->avahi_poll->mainloop->io_enable(w->io_event, translate_io_flags(event));
}
-
+
static AvahiWatchEvent watch_get_events(AvahiWatch *w) {
assert(w);
return w->current_event;
}
-
+
static void watch_free(AvahiWatch *w) {
assert(w);
static void timeout_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *tv, void *userdata) {
AvahiTimeout *t = userdata;
-
+
assert(a);
assert(e);
assert(t);
assert(api);
assert(callback);
-
+
p = api->userdata;
assert(p);
t->avahi_poll = p;
t->callback = callback;
t->userdata = userdata;
-
+
t->time_event = tv ? p->mainloop->time_new(p->mainloop, tv, timeout_callback, t) : NULL;
return t;
}
-
+
static void timeout_update(AvahiTimeout *t, const struct timeval *tv) {
assert(t);
t->time_event = NULL;
}
}
-
+
static void timeout_free(AvahiTimeout *t) {
assert(t);
pa_avahi_poll *p;
assert(m);
-
+
p = pa_xnew(pa_avahi_poll, 1);
-
+
p->api.userdata = p;
p->api.watch_new = watch_new;
p->api.watch_update = watch_update;
p->api.timeout_update = timeout_update;
p->api.timeout_free = timeout_free;
p->mainloop = m;
-
+
return &p->api;
}
assert(api);
p = api->userdata;
assert(p);
-
+
pa_xfree(p);
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
assert(c && t && buf);
pa_strbuf_puts(buf, "Available commands:\n");
-
+
for (command = commands; command->name; command++)
if (command->help)
pa_strbuf_printf(buf, " %-25s %s\n", command->name, command->help);
[PA_MEMBLOCK_FIXED] = "FIXED",
[PA_MEMBLOCK_IMPORTED] = "IMPORTED",
};
-
+
assert(c);
assert(t);
stat = pa_mempool_get_stat(c->mempool);
-
+
pa_strbuf_printf(buf, "Memory blocks currently allocated: %u, size: %s.\n",
(unsigned) AO_load_acquire_read((AO_t*) &stat->n_allocated),
pa_bytes_snprint(s, sizeof(s), (size_t) AO_load_acquire_read((AO_t*) &stat->allocated_size)));
type_table[k],
(unsigned) AO_load_acquire_read(&stat->n_allocated_by_type[k]),
(unsigned) AO_load_acquire_read(&stat->n_accumulated_by_type[k]));
-
+
return 0;
}
pa_strbuf_puts(buf, "You need to specify the module name and optionally arguments.\n");
return -1;
}
-
+
if (!(m = pa_module_load(c, name, pa_tokenizer_get(t, 2)))) {
pa_strbuf_puts(buf, "Module load failed.\n");
return -1;
}
pa_autoload_add(c, a, strstr(pa_tokenizer_get(t, 0), "sink") ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE, b, pa_tokenizer_get(t, 3), NULL);
-
+
return 0;
}
static int pa_cli_command_autoload_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
const char *name;
assert(c && t && buf && fail);
-
+
if (!(name = pa_tokenizer_get(t, 1))) {
pa_strbuf_puts(buf, "You need to specify a device name\n");
return -1;
return -1;
}
- return 0;
+ return 0;
}
static int pa_cli_command_autoload_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
assert(t);
pa_mempool_vacuum(c->mempool);
-
+
return 0;
}
time_t now;
void *i;
pa_autoload_entry *a;
-
+
assert(c && t);
time(&now);
pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime(&now));
#endif
-
+
for (m = pa_idxset_first(c->modules, &idx); m; m = pa_idxset_next(c->modules, &idx)) {
if (m->auto_unload)
continue;
if (c->autoload_hashmap) {
nl = 0;
-
+
i = NULL;
while ((a = pa_hashmap_iterate(c->autoload_hashmap, &i, NULL))) {
pa_strbuf_puts(buf, "\n");
nl = 1;
}
-
+
pa_strbuf_printf(buf, "add-autoload-%s %s %s", a->type == PA_NAMEREG_SINK ? "sink" : "source", a->name, a->module);
-
+
if (a->argument)
pa_strbuf_printf(buf, " %s", a->argument);
-
+
pa_strbuf_puts(buf, "\n");
}
}
nl = 0;
-
+
if ((p = pa_namereg_get_default_sink_name(c))) {
if (!nl) {
pa_strbuf_puts(buf, "\n");
int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, int *fail) {
const char *cs;
-
+
cs = s+strspn(s, whitespace);
if (*cs == '#' || !*cs)
const struct command*command;
int unknown = 1;
size_t l;
-
+
l = strcspn(cs, whitespace);
- for (command = commands; command->name; command++)
+ for (command = commands; command->name; command++)
if (strlen(command->name) == l && !strncmp(cs, command->name, l)) {
int ret;
pa_tokenizer *t = pa_tokenizer_new(cs, command->args);
if (ret < 0 && *fail)
return -1;
-
+
break;
}
while (*p) {
size_t l = strcspn(p, linebreak);
char *line = pa_xstrndup(p, l);
-
+
if (pa_cli_command_execute_line(c, line, buf, fail) < 0&& *fail) {
pa_xfree(line);
return -1;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
assert(s);
pa_strbuf_printf(s, "%u module(s) loaded.\n", pa_idxset_size(c->modules));
-
+
for (m = pa_idxset_first(c->modules, &idx); m; m = pa_idxset_next(c->modules, &idx))
pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\targument: <%s>\n\tused: %i\n\tauto unload: %s\n", m->index, m->name, m->argument, m->n_used, m->auto_unload ? "yes" : "no");
-
+
return pa_strbuf_tostring_free(s);
}
assert(s);
pa_strbuf_printf(s, "%u client(s) logged in.\n", pa_idxset_size(c->clients));
-
+
for (client = pa_idxset_first(c->clients, &idx); client; client = pa_idxset_next(c->clients, &idx)) {
pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\tdriver: <%s>\n", client->index, client->name, client->driver);
if (client->owner)
pa_strbuf_printf(s, "\towner module: <%u>\n", client->owner->index);
}
-
+
return pa_strbuf_tostring_free(s);
}
for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx)) {
char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
-
+
pa_strbuf_printf(
s,
" %c index: %u\n"
if (sink->description)
pa_strbuf_printf(s, "\tdescription: <%s>\n", sink->description);
}
-
+
return pa_strbuf_tostring_free(s);
}
for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) {
char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
-
-
+
+
pa_strbuf_printf(
s,
" %c index: %u\n"
pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec),
pa_channel_map_snprint(cm, sizeof(cm), &source->channel_map));
- if (source->monitor_of)
+ if (source->monitor_of)
pa_strbuf_printf(s, "\tmonitor_of: <%u>\n", source->monitor_of->index);
if (source->owner)
pa_strbuf_printf(s, "\towner module: <%u>\n", source->owner->index);
if (source->description)
pa_strbuf_printf(s, "\tdescription: <%s>\n", source->description);
}
-
+
return pa_strbuf_tostring_free(s);
}
for (o = pa_idxset_first(c->source_outputs, &idx); o; o = pa_idxset_next(c->source_outputs, &idx)) {
char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
-
+
assert(o->source);
-
+
pa_strbuf_printf(
s,
" index: %u\n"
if (o->client)
pa_strbuf_printf(s, "\tclient: <%u> '%s'\n", o->client->index, o->client->name);
}
-
+
return pa_strbuf_tostring_free(s);
}
char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
assert(i->sink);
-
+
pa_strbuf_printf(
s,
" index: %u\n"
if (i->client)
pa_strbuf_printf(s, "\tclient: <%u> '%s'\n", i->client->index, i->client->name);
}
-
+
return pa_strbuf_tostring_free(s);
}
for (e = pa_idxset_first(c->scache, &idx); e; e = pa_idxset_next(c->scache, &idx)) {
double l = 0;
char ss[PA_SAMPLE_SPEC_SNPRINT_MAX] = "n/a", cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX] = "n/a";
-
+
if (e->memchunk.memblock) {
pa_sample_spec_snprint(ss, sizeof(ss), &e->sample_spec);
pa_channel_map_snprint(cm, sizeof(cm), &e->channel_map);
l = (double) e->memchunk.length / pa_bytes_per_second(&e->sample_spec);
}
-
+
pa_strbuf_printf(
s,
" name: <%s>\n"
for (i = 0; i < 8; i++) {
char *t = NULL;
-
+
switch (i) {
- case 0:
+ case 0:
t = pa_sink_list_to_string(c);
break;
case 1:
case 3:
t = pa_source_output_list_to_string(c);
break;
- case 4:
+ case 4:
t = pa_client_list_to_string(c);
break;
case 5:
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
c->client->kill = client_kill;
c->client->userdata = c;
c->client->owner = m;
-
+
pa_ioline_set_callback(c->line, line_callback, c);
pa_ioline_puts(c->line, "Welcome to PulseAudio! Use \"help\" for usage information.\n"PROMPT);
c->fail = c->kill_requested = c->defer_kill = 0;
-
+
return c;
}
pa_cli *c;
assert(client && client->userdata);
c = client->userdata;
-
+
pa_log_debug("CLI client killed.");
if (c->defer_kill)
c->kill_requested = 1;
if (c->kill_requested) {
if (c->eof_callback)
c->eof_callback(c, c->userdata);
- } else
+ } else
pa_ioline_puts(line, PROMPT);
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_NEW, c->index);
pa_core_check_quit(core);
-
+
return c;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/* Run the user supplied parser for an assignment */
static int next_assignment(const char *filename, unsigned line, const pa_config_item *t, const char *lvalue, const char *rvalue, void *userdata) {
assert(filename && t && lvalue && rvalue);
-
+
for (; t->parse; t++)
if (!strcmp(lvalue, t->lvalue))
return t->parse(filename, line, lvalue, rvalue, t->data, userdata);
pa_log("[%s:%u] Unknown lvalue '%s'.", filename, line, lvalue);
-
+
return -1;
}
/* Returns non-zero when c is contained in s */
static int in_string(char c, const char *s) {
assert(s);
-
+
for (; *s; s++)
if (*s == c)
return 1;
-
+
return 0;
}
if ((c = strpbrk(b, COMMENTS)))
*c = 0;
-
+
if (!*b)
return 0;
unsigned line = 0;
int do_close = !f;
assert(filename && t);
-
+
if (!f && !(f = fopen(filename, "r"))) {
if (errno == ENOENT) {
r = 0;
goto finish;
}
-
+
pa_log_warn("WARNING: failed to open configuration file '%s': %s",
filename, pa_cstrerror(errno));
goto finish;
if (!fgets(l, sizeof(l), f)) {
if (feof(f))
break;
-
+
pa_log_warn("WARNING: failed to read configuration file '%s': %s",
filename, pa_cstrerror(errno));
goto finish;
}
-
+
if (parse_line(filename, ++line, t, l, userdata) < 0)
goto finish;
}
-
+
r = 0;
-
+
finish:
if (do_close && f)
fclose(f);
-
+
return r;
}
pa_log("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue);
return -1;
}
-
+
*i = (int) k;
- return 0;
+ return 0;
}
int pa_config_parse_bool(const char *filename, unsigned line, const char *lvalue, const char *rvalue, void *data, PA_GCC_UNUSED void *userdata) {
int *b = data, k;
assert(filename && lvalue && rvalue && data);
-
+
if ((k = pa_parse_boolean(rvalue)) < 0) {
pa_log("[%s:%u] Failed to parse boolean value: %s", filename, line, rvalue);
return -1;
}
-
+
*b = k;
-
+
return 0;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_memblock_unref(e->memchunk.memblock);
pa_xfree(e->filename);
-
+
assert(e->core == c);
pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_CHANGE, e->index);
if (pa_sound_file_load(c->mempool, filename, &ss, &map, &chunk) < 0)
return -1;
-
+
r = pa_scache_add_item(c, name, &ss, &map, &chunk, idx);
pa_memblock_unref(chunk.memblock);
e->lazy = 1;
e->filename = pa_xstrdup(filename);
-
+
if (!c->scache_auto_unload_event) {
struct timeval ntv;
pa_gettimeofday(&ntv);
pa_scache_entry *e;
char *t;
pa_cvolume r;
-
+
assert(c);
assert(name);
assert(sink);
if (e->volume.channels > e->sample_spec.channels)
e->volume.channels = e->sample_spec.channels;
}
-
+
if (!e->memchunk.memblock)
return -1;
if (e->lazy)
time(&e->last_used_time);
-
+
return 0;
}
if (!c->scache || !pa_idxset_size(c->scache))
return 0;
-
+
for (e = pa_idxset_first(c->scache, &idx); e; e = pa_idxset_next(c->scache, &idx))
if (e->memchunk.memblock)
sum += e->memchunk.length;
if (!c->scache || !pa_idxset_size(c->scache))
return;
-
+
time(&now);
for (e = pa_idxset_first(c->scache, &idx); e; e = pa_idxset_next(c->scache, &idx)) {
if (e->last_used_time + c->scache_idle_time > now)
continue;
-
+
pa_memblock_unref(e->memchunk.memblock);
e->memchunk.memblock = NULL;
e->memchunk.index = e->memchunk.length = 0;
const char *e;
e = pa_path_get_filename(pathname);
-
+
if (stat(pathname, &st) < 0) {
pa_log("stat('%s'): %s", pathname, pa_cstrerror(errno));
return;
for (i = 0; i < p.gl_pathc; i++)
add_file(c, p.gl_pathv[i]);
-
+
globfree(&p);
#else
return -1;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_core *core;
uint32_t index;
char *name;
-
+
pa_cvolume volume;
pa_sample_spec sample_spec;
pa_channel_map channel_map;
pa_memchunk memchunk;
char *filename;
-
+
int lazy;
time_t last_used_time;
} pa_scache_entry;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/* Allocate a new subscription object for the given subscription mask. Use the specified callback function and user data */
pa_subscription* pa_subscription_new(pa_core *c, pa_subscription_mask_t m, pa_subscription_cb_t callback, void *userdata) {
pa_subscription *s;
-
+
assert(c);
assert(m);
assert(callback);
void pa_subscription_free(pa_subscription*s) {
assert(s);
assert(!s->dead);
-
+
s->dead = 1;
sched_event(s->core);
}
if (!s->next)
s->core->subscription_event_last = s->prev;
-
+
PA_LLIST_REMOVE(pa_subscription_event, s->core->subscription_event_queue, s);
pa_xfree(s);
}
/* Free all subscription objects */
void pa_subscription_free_all(pa_core *c) {
assert(c);
-
+
while (c->subscriptions)
free_subscription(c->subscriptions);
static void defer_cb(pa_mainloop_api *m, pa_defer_event *de, void *userdata) {
pa_core *c = userdata;
pa_subscription *s;
-
+
assert(c->mainloop == m);
assert(c);
assert(c->subscription_defer_event == de);
pa_subscription_event *e = c->subscription_event_queue;
for (s = c->subscriptions; s; s = s->next) {
-
+
if (!s->dead && pa_subscription_match_flags(s->mask, e->type))
s->callback(c, e->type, e->index, s->userdata);
}
}
/* Remove dead subscriptions */
-
+
s = c->subscriptions;
while (s) {
pa_subscription *n = s->next;
c->subscription_defer_event = c->mainloop->defer_new(c->mainloop, defer_cb, c);
assert(c->subscription_defer_event);
}
-
+
c->mainloop->defer_enable(c->subscription_defer_event, 1);
}
/* No need for queuing subscriptions of noone is listening */
if (!c->subscriptions)
return;
-
+
if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) != PA_SUBSCRIPTION_EVENT_NEW) {
pa_subscription_event *i, *n;
-
+
/* Check for duplicates */
for (i = c->subscription_event_last; i; i = n) {
n = i->prev;
-
+
/* not the same object type */
if (((t ^ i->type) & PA_SUBSCRIPTION_EVENT_FACILITY_MASK))
continue;
-
+
/* not the same object */
if (i->index != index)
continue;
e->type = t;
e->index = index;
- PA_LLIST_INSERT_AFTER(pa_subscription_event, c->subscription_event_queue, c->subscription_event_last, e);
+ PA_LLIST_INSERT_AFTER(pa_subscription_event, c->subscription_event_queue, c->subscription_event_last, e);
c->subscription_event_last = e;
#ifdef DEBUG
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
int pa_make_secure_dir(const char* dir, mode_t m, uid_t uid, gid_t gid) {
struct stat st;
int r;
-
+
assert(dir);
#ifdef OS_IS_WIN32
umask(u);
}
#endif
-
+
if (r < 0 && errno != EEXIST)
return -1;
gid = getgid();
chown(dir, uid, gid);
#endif
-
+
#ifdef HAVE_CHMOD
chmod(dir, m);
#endif
-
+
#ifdef HAVE_LSTAT
if (lstat(dir, &st) < 0)
#else
if (stat(dir, &st) < 0)
#endif
goto fail;
-
+
#ifndef OS_IS_WIN32
if (!S_ISDIR(st.st_mode) ||
(st.st_uid != uid) ||
#else
pa_log_warn("secure directory creation not supported on Win32.");
#endif
-
+
return 0;
-
+
fail:
rmdir(dir);
return -1;
if (!(dir = pa_parent_dir(fn)))
goto finish;
-
+
if (pa_make_secure_dir(dir, m, uid, gid) < 0)
goto finish;
ret = 0;
-
+
finish:
pa_xfree(dir);
return ret;
if (!type || *type == 0) {
ssize_t r;
-
+
if ((r = recv(fd, buf, count, 0)) >= 0)
return r;
}
#endif
-
+
return read(fd, buf, count);
}
if ((r = send(fd, buf, count, MSG_NOSIGNAL)) >= 0)
return r;
-
+
#ifdef OS_IS_WIN32
if (WSAGetLastError() != WSAENOTSOCK) {
errno = WSAGetLastError();
ssize_t pa_loop_read(int fd, void*data, size_t size, int *type) {
ssize_t ret = 0;
int _type;
-
+
assert(fd >= 0);
assert(data);
assert(size);
if (r == 0)
break;
-
+
ret += r;
data = (uint8_t*) data + r;
size -= r;
if (r == 0)
break;
-
+
ret += r;
data = (const uint8_t*) data + r;
size -= r;
/* If POSIX threads are supported use thread-aware
* pthread_sigmask() function, to check if the signal is
* blocked. Otherwise fall back to sigprocmask() */
-
-#ifdef HAVE_PTHREAD
+
+#ifdef HAVE_PTHREAD
if (pthread_sigmask(SIG_SETMASK, NULL, &set) < 0) {
#endif
if (sigprocmask(SIG_SETMASK, NULL, &set) < 0) {
return;
/* Check whether the signal is trapped */
-
+
if (sigaction(sig, NULL, &sa) < 0) {
pa_log("sigaction(): %s", pa_cstrerror(errno));
return;
}
-
+
if (sa.sa_handler != SIG_DFL)
return;
-
+
pa_log("WARNING: %s is not trapped. This might cause malfunction!", pa_strsignal(sig));
#else /* HAVE_SIGACTION */
pa_log("WARNING: %s might not be trapped. This might cause malfunction!", pa_strsignal(sig));
char *pa_sprintf_malloc(const char *format, ...) {
int size = 100;
char *c = NULL;
-
+
assert(format);
-
+
for(;;) {
int r;
va_list ap;
va_start(ap, format);
r = vsnprintf(c, size, format, ap);
va_end(ap);
-
+
if (r > -1 && r < size)
return c;
if (r > -1) /* glibc 2.1 */
- size = r+1;
+ size = r+1;
else /* glibc 2.0 */
size *= 2;
}
char *pa_vsprintf_malloc(const char *format, va_list ap) {
int size = 100;
char *c = NULL;
-
+
assert(format);
-
+
for(;;) {
int r;
va_list aq;
r = vsnprintf(c, size, format, aq);
va_end(aq);
-
+
if (r > -1 && r < size)
return c;
if (r > -1) /* glibc 2.1 */
- size = r+1;
+ size = r+1;
else /* glibc 2.0 */
size *= 2;
}
#ifdef HAVE_SYS_RESOURCE_H
if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0)
pa_log_warn("setpriority(): %s", pa_cstrerror(errno));
- else
- pa_log_info("Successfully gained nice level %i.", NICE_LEVEL);
+ else
+ pa_log_info("Successfully gained nice level %i.", NICE_LEVEL);
#endif
-
+
#ifdef _POSIX_PRIORITY_SCHEDULING
{
struct sched_param sp;
pa_log("sched_getparam(): %s", pa_cstrerror(errno));
return;
}
-
+
sp.sched_priority = 1;
if (sched_setscheduler(0, SCHED_FIFO, &sp) < 0) {
pa_log_warn("sched_setscheduler(): %s", pa_cstrerror(errno));
return;
}
- pa_log_info("Successfully enabled SCHED_FIFO scheduling.");
+ pa_log_info("Successfully enabled SCHED_FIFO scheduling.");
}
#endif
if (!SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS))
pa_log_warn("SetPriorityClass() failed: 0x%08X", GetLastError());
else
- pa_log_info("Successfully gained high priority class.");
+ pa_log_info("Successfully gained high priority class.");
#endif
}
if ((v = fcntl(fd, F_GETFD, 0)) < 0)
return -1;
-
+
v = (v & ~FD_CLOEXEC) | (b ? FD_CLOEXEC : 0);
-
+
if (fcntl(fd, F_SETFD, v) < 0)
return -1;
-#endif
+#endif
return 0;
}
/* Try to parse a boolean string value.*/
int pa_parse_boolean(const char *v) {
-
+
if (!strcmp(v, "1") || v[0] == 'y' || v[0] == 'Y' || v[0] == 't' || v[0] == 'T' || !strcasecmp(v, "on"))
return 1;
else if (!strcmp(v, "0") || v[0] == 'n' || v[0] == 'N' || v[0] == 'f' || v[0] == 'F' || !strcasecmp(v, "off"))
if (!*current)
return NULL;
-
+
l = strcspn(current, delimiter);
*state = current+l;
}
r = strcmp(name, result->gr_name) == 0;
-
+
finish:
pa_xfree(data);
#else
finish:
#endif
-
+
return r;
}
int r = -1, i;
assert(n > 0);
-
+
gids = pa_xmalloc(sizeof(GETGROUPS_T)*n);
-
+
if ((n = getgroups(n, gids)) < 0) {
pa_log("getgroups(): %s", pa_cstrerror(errno));
goto finish;
}
r = 0;
-
+
finish:
pa_xfree(gids);
struct group grbuf, *gr;
char **i;
int r = -1;
-
+
g_n = sysconf(_SC_GETGR_R_SIZE_MAX);
g_buf = pa_xmalloc(g_n);
p_n = sysconf(_SC_GETPW_R_SIZE_MAX);
p_buf = pa_xmalloc(p_n);
-
+
if (getgrnam_r(name, &grbuf, g_buf, (size_t) g_n, &gr) != 0 || !gr)
goto finish;
r = 0;
for (i = gr->gr_mem; *i; i++) {
struct passwd pwbuf, *pw;
-
+
if (getpwnam_r(*i, &pwbuf, p_buf, (size_t) p_n, &pw) != 0 || !pw)
continue;
int pa_own_uid_in_group(const char *name, gid_t *gid) {
return -1;
-
+
}
int pa_uid_in_group(uid_t uid, const char *name) {
struct flock flock;
/* Try a R/W lock first */
-
+
flock.l_type = b ? F_WRLCK : F_UNLCK;
flock.l_whence = SEEK_SET;
flock.l_start = 0;
if (fcntl(fd, F_SETLKW, &flock) >= 0)
return 0;
}
-
+
pa_log("%slock: %s", !b? "un" : "",
pa_cstrerror(errno));
#endif
for (;;) {
struct stat st;
-
+
if ((fd = open(fn, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR)) < 0) {
pa_log("failed to create lock file '%s': %s", fn,
pa_cstrerror(errno));
goto fail;
}
-
+
if (pa_lock_fd(fd, 1) < 0) {
pa_log("failed to lock file '%s'.", fn);
goto fail;
}
-
+
if (fstat(fd, &st) < 0) {
pa_log("failed to fstat() file '%s'.", fn);
goto fail;
/* Check wheter the file has been removed meanwhile. When yes, restart this loop, otherwise, we're done */
if (st.st_nlink >= 1)
break;
-
+
if (pa_lock_fd(fd, 0) < 0) {
pa_log("failed to unlock file '%s'.", fn);
goto fail;
}
-
+
if (close(fd) < 0) {
pa_log("failed to close file '%s'.", fn);
goto fail;
fd = -1;
}
-
+
return fd;
fail:
fn, pa_cstrerror(errno));
r = -1;
}
-
+
if (pa_lock_fd(fd, 0) < 0) {
pa_log_warn("WARNING: failed to unlock file '%s'.", fn);
r = -1;
if (lfn) {
FILE *f;
-
+
#ifdef OS_IS_WIN32
if (!ExpandEnvironmentStrings(lfn, buf, PATH_MAX))
return NULL;
fn = buf;
#endif
-
+
if ((f = fopen(fn, mode)) || errno != ENOENT) {
if (result)
*result = pa_xstrdup(fn);
pa_xfree(lfn);
return f;
}
-
+
pa_xfree(lfn);
}
}
if (result)
*result = pa_xstrdup(global);
-
+
return fopen(global, mode);
}
-
+
/* Format the specified data as a hexademical string */
char *pa_hexstr(const uint8_t* d, size_t dlength, char *s, size_t slength) {
size_t i = 0, j = 0;
if ((b = hexc(*(p++))) < 0)
return (size_t) -1;
-
+
d[j] = (uint8_t) (b << 4);
if (!*p)
/* Returns nonzero when *s starts with *pfx */
int pa_startswith(const char *s, const char *pfx) {
size_t l;
-
+
assert(s);
assert(pfx);
-
+
l = strlen(pfx);
return strlen(s) >= l && strncmp(s, pfx, l) == 0;
/* Returns nonzero when *s ends with *sfx */
int pa_endswith(const char *s, const char *sfx) {
size_t l1, l2;
-
+
assert(s);
assert(sfx);
-
+
l1 = strlen(s);
l2 = strlen(sfx);
if ((e = getenv("PULSE_RUNTIME_PATH"))) {
- if (fn)
+ if (fn)
snprintf(s, l, "%s%c%s", e, PATH_SEP, fn);
else
snprintf(s, l, "%s", e);
-
+
} else {
char u[256];
-
- if (fn)
+
+ if (fn)
snprintf(s, l, "%s%s%c%s", PA_USER_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)), PATH_SEP, fn);
else
snprintf(s, l, "%s%s", PA_USER_RUNTIME_PATH_PREFIX, pa_get_user_name(u, sizeof(u)));
}
-
+
#ifdef OS_IS_WIN32
{
return -1;
*ret_i = (int32_t) l;
-
+
return 0;
}
return -1;
*ret_u = (uint32_t) l;
-
+
return 0;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_property_init(c);
pa_random(&c->cookie, sizeof(c->cookie));
-
+
#ifdef SIGPIPE
pa_check_signal_is_blocked(SIGPIPE);
#endif
assert(pa_idxset_isempty(c->clients));
pa_idxset_free(c->clients, NULL, NULL);
-
+
assert(pa_idxset_isempty(c->sinks));
pa_idxset_free(c->sinks, NULL, NULL);
assert(pa_idxset_isempty(c->sources));
pa_idxset_free(c->sources, NULL, NULL);
-
+
assert(pa_idxset_isempty(c->source_outputs));
pa_idxset_free(c->source_outputs, NULL, NULL);
-
+
assert(pa_idxset_isempty(c->sink_inputs));
pa_idxset_free(c->sink_inputs, NULL, NULL);
pa_hook_free(&c->hook_sink_disconnect);
pa_hook_free(&c->hook_source_output_new);
pa_hook_free(&c->hook_source_disconnect);
-
- pa_xfree(c);
+
+ pa_xfree(c);
}
static void quit_callback(pa_mainloop_api*m, pa_time_event *e, PA_GCC_UNUSED const struct timeval *tv, void *userdata) {
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/* A random value which may be used to identify this instance of
* PulseAudio. Not cryptographically secure in any way. */
uint32_t cookie;
-
+
pa_mainloop_api *mainloop;
/* idxset of all kinds of entities */
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
size = FLIST_SIZE;
assert(is_power_of_two(size));
-
+
l = pa_xnew(pa_flist, 1);
l->size = size;
l->cells = pa_xnew0(struct cell, size);
-
+
pa_atomic_store(&l->read_idx, 0);
pa_atomic_store(&l->write_idx, 0);
pa_atomic_store(&l->length, 0);
if (free_cb) {
int len, idx;
-
+
idx = reduce(l, pa_atomic_load(&l->read_idx));
len = pa_atomic_load(&l->length);
-
+
for (; len > 0; len--) {
if (pa_atomic_load(&l->cells[idx].state) == STATE_USED)
int pa_flist_push(pa_flist*l, void *p) {
int idx, len, n;
-
+
assert(l);
assert(p);
if (len > N_EXTRA_SCAN)
pa_log("WARNING: Didn't find free cell after %u iterations.", len);
#endif
-
+
return -1;
}
void* pa_flist_pop(pa_flist*l) {
int idx, len, n;
-
+
assert(l);
n = len = pa_atomic_load(&l->length) + N_EXTRA_SCAN;
if (len > N_EXTRA_SCAN)
pa_log("WARNING: Didn't find used cell after %u iterations.", len);
#endif
-
+
return NULL;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
#define st_14linear2ulaw(sw) (_st_14linear2ulaw[(sw + 0x2000)])
#define st_ulaw2linear16(uc) (_st_ulaw2linear16[uc])
#else
-unsigned char st_14linear2ulaw(int16_t pcm_val);
+unsigned char st_14linear2ulaw(int16_t pcm_val);
int16_t st_ulaw2linear16(unsigned char);
#endif
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
unsigned size;
struct hashmap_entry **data;
struct hashmap_entry *first_entry;
-
+
unsigned n_entries;
pa_hash_func_t hash_func;
pa_compare_func_t compare_func;
pa_hashmap *pa_hashmap_new(pa_hash_func_t hash_func, pa_compare_func_t compare_func) {
pa_hashmap *h;
-
+
h = pa_xnew(pa_hashmap, 1);
h->data = pa_xnew0(struct hashmap_entry*, h->size = BUCKETS);
h->first_entry = NULL;
h->n_entries = 0;
h->hash_func = hash_func ? hash_func : pa_idxset_trivial_hash_func;
h->compare_func = compare_func ? compare_func : pa_idxset_trivial_compare_func;
-
+
return h;
}
free_func(h->first_entry->value, userdata);
remove(h, h->first_entry);
}
-
+
pa_xfree(h->data);
pa_xfree(h);
}
if ((e = get(h, hash, key)))
return -1;
-
+
e = pa_xnew(struct hashmap_entry, 1);
e->hash = hash;
e->key = key;
e->value = value;
-
+
e->previous = NULL;
e->next = h->first_entry;
if (h->first_entry)
h->first_entry->previous = e;
h->first_entry = e;
-
+
e->bucket_previous = NULL;
e->bucket_next = h->data[hash];
if (h->data[hash])
h->data[hash]->bucket_previous = e;
h->data[hash] = e;
-
+
h->n_entries ++;
return 0;
}
struct hashmap_entry *e;
unsigned hash;
void *data;
-
+
assert(h);
hash = h->hash_func(key) % h->size;
assert(h);
assert(state);
- if (!*state)
+ if (!*state)
*state = h->first_entry;
else
*state = ((struct hashmap_entry*) *state)->next;
if (key)
*key = ((struct hashmap_entry*) *state)->key;
-
+
return ((struct hashmap_entry*) *state)->value;
}
void* pa_hashmap_steal_first(pa_hashmap *h) {
void *data;
-
+
assert(h);
if (!h->first_entry)
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
if (hook->last == slot)
hook->last = slot->prev;
-
+
PA_LLIST_REMOVE(pa_hook_slot, hook->slots, slot);
-
+
pa_xfree(slot);
}
while (hook->slots)
slot_free(hook, hook->slots);
-
+
pa_hook_init(hook, NULL);
}
pa_hook_slot* pa_hook_connect(pa_hook *hook, pa_hook_cb_t cb, void *data) {
pa_hook_slot *slot;
-
+
assert(cb);
slot = pa_xnew(pa_hook_slot, 1);
slot->dead = 0;
slot->callback = cb;
slot->data = data;
-
+
PA_LLIST_INSERT_AFTER(pa_hook_slot, hook->slots, hook->last, slot);
hook->last = slot;
-
+
return slot;
}
void pa_hook_slot_free(pa_hook_slot *slot) {
assert(slot);
assert(!slot->dead);
-
+
if (slot->hook->firing > 0) {
slot->dead = 1;
slot->hook->n_dead++;
pa_hook_result_t pa_hook_fire(pa_hook *hook, void *data) {
pa_hook_slot *slot, *next;
pa_hook_result_t result = PA_HOOK_OK;
-
+
assert(hook);
hook->firing ++;
for (slot = hook->slots; slot; slot = slot->next) {
if (slot->dead)
continue;
-
+
if ((result = slot->callback(hook->data, data, slot->data)) != PA_HOOK_OK)
break;
}
-
+
hook->firing --;
-
+
for (slot = hook->slots; hook->n_dead > 0 && slot; slot = next) {
next = slot->next;
-
+
if (slot->dead) {
slot_free(hook, slot);
hook->n_dead--;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
struct pa_idxset {
pa_hash_func_t hash_func;
pa_compare_func_t compare_func;
-
+
unsigned hash_table_size, n_entries;
idxset_entry **hash_table, **array, *iterate_list_head, *iterate_list_tail;
uint32_t index, start_index, array_size;
unsigned pa_idxset_string_hash_func(const void *p) {
unsigned hash = 0;
const char *c;
-
+
for (c = p; *c; c++)
hash = 31 * hash + *c;
while (s->iterate_list_head) {
idxset_entry *e = s->iterate_list_head;
s->iterate_list_head = s->iterate_list_head->iterate_next;
-
+
if (free_func)
free_func(e->data, userdata);
pa_xfree(e);
l = idx - s->start_index - i + 100;
n = pa_xnew0(idxset_entry*, l);
-
+
for (j = 0; j < s->array_size-i; j++)
n[j] = s->array[i+j];
pa_xfree(s->array);
-
+
s->array = n;
s->array_size = l;
s->start_index += i;
static idxset_entry** array_index(pa_idxset*s, uint32_t idx) {
if (idx >= s->start_index + s->array_size)
return NULL;
-
+
if (idx < s->start_index)
return NULL;
-
+
return s->array + idx - s->start_index;
}
int pa_idxset_put(pa_idxset*s, void *p, uint32_t *idx) {
unsigned h;
idxset_entry *e, **a;
-
+
assert(s);
assert(p);
if ((e = hash_scan(s, s->hash_table[h], p))) {
if (idx)
*idx = e->index;
-
+
return -1;
}
s->iterate_list_head = e;
}
s->iterate_list_tail = e;
-
+
s->n_entries++;
assert(s->n_entries >= 1);
-
+
if (idx)
*idx = e->index;
void* pa_idxset_get_by_index(pa_idxset*s, uint32_t idx) {
idxset_entry **a;
assert(s);
-
+
if (!(a = array_index(s, idx)))
return NULL;
unsigned h;
idxset_entry *e;
assert(s && p);
-
+
assert(s->hash_func);
h = s->hash_func(p) % s->hash_table_size;
a = array_index(s, e->index);
assert(a && *a && *a == e);
*a = NULL;
-
+
/* Remove from linked list */
if (e->iterate_next)
e->iterate_next->iterate_prev = e->iterate_prev;
else
s->iterate_list_tail = e->iterate_prev;
-
+
if (e->iterate_prev)
e->iterate_prev->iterate_next = e->iterate_next;
else
void* pa_idxset_remove_by_index(pa_idxset*s, uint32_t idx) {
idxset_entry **a;
void *data;
-
+
assert(s);
if (!(a = array_index(s, idx)))
data = (*a)->data;
remove_entry(s, *a);
-
- return data;
+
+ return data;
}
void* pa_idxset_remove_by_data(pa_idxset*s, const void *data, uint32_t *idx) {
idxset_entry *e;
unsigned h;
void *r;
-
+
assert(s->hash_func);
h = s->hash_func(data) % s->hash_table_size;
if (!e)
return NULL;
-
+
*idx = e->index;
return e->data;
}
if ((a = array_index(s, *idx)) && *a)
e = (*a)->iterate_next;
-
+
if (e) {
*idx = e->index;
return e->data;
e = n;
}
-
+
return 0;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_iochannel_cb_t callback;
void*userdata;
-
+
int readable;
int writable;
int hungup;
-
+
int no_close;
pa_io_event* input_event, *output_event;
if (io->input_event == io->output_event && io->input_event) {
pa_io_event_flags_t f = PA_IO_EVENT_NULL;
assert(io->input_event);
-
+
if (!io->readable)
f |= PA_IO_EVENT_INPUT;
if (!io->writable)
static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
pa_iochannel *io = userdata;
int changed = 0;
-
+
assert(m);
assert(e);
assert(fd >= 0);
changed = 1;
assert(e == io->input_event);
}
-
+
if ((f & PA_IO_EVENT_OUTPUT) && !io->writable) {
io->writable = 1;
changed = 1;
if (changed) {
enable_mainloop_sources(io);
-
+
if (io->callback)
io->callback(io, io->userdata);
}
pa_iochannel* pa_iochannel_new(pa_mainloop_api*m, int ifd, int ofd) {
pa_iochannel *io;
-
+
assert(m);
assert(ifd >= 0 || ofd >= 0);
if (io->input_event)
io->mainloop->io_free(io->input_event);
-
+
if (io->output_event && (io->output_event != io->input_event))
io->mainloop->io_free(io->output_event);
if (!io->no_close) {
if (io->ifd >= 0)
-
+
close(io->ifd);
if (io->ofd >= 0 && io->ofd != io->ifd)
close(io->ofd);
}
-
+
pa_xfree(io);
}
int pa_iochannel_is_readable(pa_iochannel*io) {
assert(io);
-
+
return io->readable || io->hungup;
}
int pa_iochannel_is_writable(pa_iochannel*io) {
assert(io);
-
+
return io->writable && !io->hungup;
}
int pa_iochannel_is_hungup(pa_iochannel*io) {
assert(io);
-
+
return io->hungup;
}
ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l) {
ssize_t r;
-
+
assert(io);
assert(data);
assert(l);
ssize_t pa_iochannel_read(pa_iochannel*io, void*data, size_t l) {
ssize_t r;
-
+
assert(io);
assert(data);
assert(io->ifd >= 0);
int pa_iochannel_creds_supported(pa_iochannel *io) {
struct sockaddr_un sa;
socklen_t l;
-
+
assert(io);
assert(io->ifd >= 0);
assert(io->ofd == io->ifd);
l = sizeof(sa);
-
+
if (getsockname(io->ifd, (struct sockaddr*) &sa, &l) < 0)
return 0;
assert(io);
assert(io->ifd >= 0);
-
+
if (setsockopt(io->ifd, SOL_SOCKET, SO_PASSCRED, &t, sizeof(t)) < 0) {
pa_log_error("setsockopt(SOL_SOCKET, SO_PASSCRED): %s", pa_cstrerror(errno));
return -1;
uint8_t cmsg_data[CMSG_SPACE(sizeof(struct ucred))];
struct ucred *u;
struct cmsghdr *cmsg;
-
+
assert(io);
assert(data);
assert(l);
u->uid = getuid();
u->gid = getgid();
}
-
+
memset(&mh, 0, sizeof(mh));
mh.msg_name = NULL;
mh.msg_namelen = 0;
struct msghdr mh;
struct iovec iov;
uint8_t cmsg_data[CMSG_SPACE(sizeof(struct ucred))];
-
+
assert(io);
assert(data);
assert(l);
struct cmsghdr *cmsg;
*creds_valid = 0;
-
+
for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
-
+
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) {
struct ucred u;
assert(cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)));
io->readable = 0;
enable_mainloop_sources(io);
}
-
+
return r;
}
void pa_iochannel_set_callback(pa_iochannel*io, pa_iochannel_cb_t _callback, void *userdata) {
assert(io);
-
+
io->callback = _callback;
io->userdata = userdata;
}
void pa_iochannel_set_noclose(pa_iochannel*io, int b) {
assert(io);
-
+
io->no_close = b;
}
assert(io);
assert(s);
assert(l);
-
+
pa_socket_peer_to_string(io->ifd, s, l);
}
int pa_iochannel_socket_set_rcvbuf(pa_iochannel *io, size_t l) {
assert(io);
-
+
return pa_socket_set_rcvbuf(io->ifd, l);
}
int pa_iochannel_socket_set_sndbuf(pa_iochannel *io, size_t l) {
assert(io);
-
+
return pa_socket_set_sndbuf(io->ofd, l);
}
pa_mainloop_api* pa_iochannel_get_mainloop_api(pa_iochannel *io) {
assert(io);
-
+
return io->mainloop;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_ioline* pa_ioline_new(pa_iochannel *io) {
pa_ioline *l;
assert(io);
-
+
l = pa_xnew(pa_ioline, 1);
l->io = io;
l->dead = 0;
l->mainloop->defer_enable(l->defer_event, 0);
l->defer_close = 0;
-
+
pa_iochannel_set_callback(io, io_callback, l);
-
+
return l;
}
assert(l->ref >= 1);
l->dead = 1;
-
+
if (l->io) {
pa_iochannel_free(l->io);
l->io = NULL;
void pa_ioline_puts(pa_ioline *l, const char *c) {
size_t len;
-
+
assert(l);
assert(l->ref >= 1);
assert(c);
if (l->dead)
return;
-
+
len = strlen(c);
if (len > BUFFER_LIMIT - l->wbuf_valid_length)
len = BUFFER_LIMIT - l->wbuf_valid_length;
if (len) {
assert(l->wbuf_length >= l->wbuf_valid_length);
-
+
/* In case the allocated buffer is too small, enlarge it. */
if (l->wbuf_valid_length + len > l->wbuf_length) {
size_t n = l->wbuf_valid_length+len;
l->wbuf_length = n;
l->wbuf_index = 0;
} else if (l->wbuf_index + l->wbuf_valid_length + len > l->wbuf_length) {
-
+
/* In case the allocated buffer fits, but the current index is too far from the start, move it to the front. */
memmove(l->wbuf, l->wbuf+l->wbuf_index, l->wbuf_valid_length);
l->wbuf_index = 0;
}
-
+
assert(l->wbuf_index + l->wbuf_valid_length + len <= l->wbuf_length);
-
+
/* Append the new string */
memcpy(l->wbuf + l->wbuf_index + l->wbuf_valid_length, c, len);
l->wbuf_valid_length += len;
void pa_ioline_set_callback(pa_ioline*l, void (*callback)(pa_ioline*io, const char *s, void *userdata), void *userdata) {
assert(l);
assert(l->ref >= 1);
-
+
l->callback = callback;
l->userdata = userdata;
}
l->callback(l, NULL, l->userdata);
l->callback = NULL;
}
-
+
pa_ioline_close(l);
}
while (!l->dead && l->rbuf_valid_length > skip) {
char *e, *p;
size_t m;
-
+
if (!(e = memchr(l->rbuf + l->rbuf_index + skip, '\n', l->rbuf_valid_length - skip)))
break;
*e = 0;
-
+
p = l->rbuf + l->rbuf_index;
m = strlen(p);
size_t len;
len = l->rbuf_length - l->rbuf_index - l->rbuf_valid_length;
-
+
/* Check if we have to enlarge the read buffer */
if (len < READ_SIZE) {
size_t n = l->rbuf_valid_length+READ_SIZE;
-
+
if (n >= BUFFER_LIMIT)
n = BUFFER_LIMIT;
-
+
if (l->rbuf_length >= n) {
/* The current buffer is large enough, let's just move the data to the front */
if (l->rbuf_valid_length)
l->rbuf = new;
l->rbuf_length = n;
}
-
+
l->rbuf_index = 0;
}
-
+
len = l->rbuf_length - l->rbuf_index - l->rbuf_valid_length;
-
+
assert(len >= READ_SIZE);
-
+
/* Read some data */
if ((r = pa_iochannel_read(l->io, l->rbuf+l->rbuf_index+l->rbuf_valid_length, len)) <= 0) {
if (r < 0) {
failure(l, 0);
} else
failure(l, 1);
-
+
return -1;
}
-
+
l->rbuf_valid_length += r;
-
+
/* Look if a line has been terminated in the newly read data */
scan_for_lines(l, l->rbuf_valid_length - r);
}
-
+
return 0;
}
assert(l && l->ref >= 1);
while (!l->dead && pa_iochannel_is_writable(l->io) && l->wbuf_valid_length) {
-
+
if ((r = pa_iochannel_write(l->io, l->wbuf+l->wbuf_index, l->wbuf_valid_length)) < 0) {
pa_log("write(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
failure(l, 0);
return -1;
}
-
+
l->wbuf_index += r;
l->wbuf_valid_length -= r;
-
+
/* A shortcut for the next time */
if (l->wbuf_valid_length == 0)
l->wbuf_index = 0;
}
-
+
return 0;
}
pa_ioline_ref(l);
l->mainloop->defer_enable(l->defer_event, 0);
-
+
if (!l->dead)
do_read(l);
void pa_ioline_defer_close(pa_ioline *l) {
assert(l);
assert(l->ref >= 1);
-
+
l->defer_close = 1;
if (!l->wbuf_valid_length)
void pa_ioline_printf(pa_ioline *l, const char *format, ...) {
char *t;
va_list ap;
-
+
assert(l);
assert(l->ref >= 1);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
struct acl_entry {
PA_LLIST_FIELDS(struct acl_entry);
- int family;
+ int family;
struct in_addr address_ipv4;
struct in6_addr address_ipv6;
int bits;
pa_ip_acl *acl;
assert(s);
-
+
acl = pa_xnew(pa_ip_acl, 1);
PA_LLIST_HEAD_INIT(struct acl_entry, acl->entries);
-
+
while ((a = pa_split(s, ";", &state))) {
char *slash;
struct acl_entry e, *n;
if (inet_pton(AF_INET, a, &e.address_ipv4) > 0) {
e.bits = bits == (uint32_t) -1 ? 32 : (int) bits;
-
+
if (e.bits > 32) {
pa_log("number of bits out of range: %i", e.bits);
goto fail;
if (e.bits < 32 && (uint32_t) (ntohl(e.address_ipv4.s_addr) << e.bits) != 0)
pa_log_warn("WARNING: Host part of ACL entry '%s/%u' is not zero!", a, e.bits);
-
+
} else if (inet_pton(AF_INET6, a, &e.address_ipv6) > 0) {
e.bits = bits == (uint32_t) -1 ? 128 : (int) bits;
for (i = 0, bits = e.bits; i < 16; i++) {
- if (bits >= 8)
+ if (bits >= 8)
bits -= 8;
else {
if ((uint8_t) ((e.address_ipv6.s6_addr[i]) << bits) != 0) {
if (t)
pa_log_warn("WARNING: Host part of ACL entry '%s/%u' is not zero!", a, e.bits);
}
-
+
} else {
pa_log("failed to parse address: %s", a);
goto fail;
n = pa_xmemdup(&e, sizeof(struct acl_entry));
PA_LLIST_PREPEND(struct acl_entry, acl->entries, n);
-
+
pa_xfree(a);
}
return acl;
-
+
fail:
pa_xfree(a);
pa_ip_acl_free(acl);
-
+
return NULL;
}
PA_LLIST_REMOVE(struct acl_entry, acl->entries, e);
pa_xfree(e);
}
-
+
pa_xfree(acl);
}
struct sockaddr_storage sa;
struct acl_entry *e;
socklen_t salen;
-
+
assert(acl);
assert(fd >= 0);
if (sa.ss_family == AF_INET6 && salen != sizeof(struct sockaddr_in6))
return -1;
-
+
for (e = acl->entries; e; e = e->next) {
if (e->family != sa.ss_family)
if (e->family == AF_INET) {
struct sockaddr_in *sai = (struct sockaddr_in*) &sa;
-
+
if (e->bits == 0 || /* this needs special handling because >> takes the right-hand side modulo 32 */
(ntohl(sai->sin_addr.s_addr ^ e->address_ipv4.s_addr) >> (32 - e->bits)) == 0)
return 1;
if (e->bits == 0)
return 1;
-
+
for (i = 0, bits = e->bits; i < 16; i++) {
if (bits >= 8) {
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
assert(_head); \
while ((*_head)->prev) \
*_head = (*_head)->prev; \
-} while (0)
+} while (0)
#define PA_LLIST_INSERT_AFTER(t,head,a,b) \
do { \
_b->prev = _a; \
_a->next = _b; \
} \
-} while (0)
-
+} while (0)
+
#endif
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
const char *func,
const char *format,
va_list ap) {
-
+
const char *e;
char *text, *t, *n, *location;
-
+
assert(level < PA_LOG_LEVEL_MAX);
assert(format);
if ((e = getenv(ENV_LOGLEVEL)))
maximal_level = atoi(e);
-
+
if (level > maximal_level)
return;
if (!*t)
continue;
-
+
switch (log_target) {
case PA_LOG_STDERR: {
const char *prefix = "", *suffix = "";
char *local_t;
-#ifndef OS_IS_WIN32
+#ifndef OS_IS_WIN32
/* Yes indeed. Useless, but fun! */
if (isatty(STDERR_FILENO)) {
if (level <= PA_LOG_ERROR) {
break;
}
-
-#ifdef HAVE_SYSLOG_H
+
+#ifdef HAVE_SYSLOG_H
case PA_LOG_SYSLOG: {
char *local_t;
}
closelog();
- break;
+ break;
}
#endif
-
+
case PA_LOG_USER: {
char *x;
x = pa_sprintf_malloc("%s%s", location, t);
user_log_func(level, x);
pa_xfree(x);
-
+
break;
}
-
+
case PA_LOG_NULL:
default:
break;
int line,
const char *func,
const char *format, ...) {
-
+
va_list ap;
va_start(ap, format);
pa_log_levelv_meta(level, file, line, func, format, ap);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
assert(base);
m = pa_xnew(pa_mcalign, 1);
-
+
m->base = base;
pa_memchunk_reset(&m->leftover);
pa_memchunk_reset(&m->current);
-
+
return m;
}
if (m->current.memblock)
pa_memblock_unref(m->current.memblock);
-
+
pa_xfree(m);
}
void pa_mcalign_push(pa_mcalign *m, const pa_memchunk *c) {
assert(m);
assert(c);
-
+
assert(c->memblock);
assert(c->length > 0);
assert(!m->current.memblock);
-
+
/* Append to the leftover memory block */
if (m->leftover.memblock) {
-
+
/* Try to merge */
if (m->leftover.memblock == c->memblock &&
m->leftover.index + m->leftover.length == c->index) {
if (m->leftover.length >= m->base) {
m->current = m->leftover;
pa_memchunk_reset(&m->leftover);
- }
+ }
} else {
size_t l;
/* We have to copy */
assert(m->leftover.length < m->base);
l = m->base - m->leftover.length;
-
+
if (l > c->length)
l = c->length;
}
} else {
/* Nothing to merge or copy, just store it */
-
+
if (c->length >= m->base)
m->current = *c;
else
m->leftover = m->current;
pa_memchunk_reset(&m->current);
}
-
+
return 0;
}
}
pa_memchunk_reset(&m->current);
-
+
return 0;
}
/* There's simply nothing */
return -1;
-
+
}
size_t pa_mcalign_csize(pa_mcalign *m, size_t l) {
assert(l > 0);
assert(!m->current.memblock);
-
+
if (m->leftover.memblock)
l += m->leftover.length;
-
+
return (l/m->base)*m->base;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* for (;;) {
* pa_memchunk input;
*
- * ... fill input ...
+ * ... fill input ...
*
* pa_mcalign_push(m, &input);
* pa_memblock_unref(input.memblock);
- *
+ *
* for (;;) {
* pa_memchunk output;
*
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
struct pa_memexport {
pa_mempool *pool;
-
+
struct memexport_slot slots[PA_MEMEXPORT_SLOTS_MAX];
PA_LLIST_HEAD(struct memexport_slot, free_slots);
PA_LLIST_HEAD(struct memexport_slot, used_slots);
/* A list of free slots that may be reused */
PA_LLIST_HEAD(struct mempool_slot, free_slots);
-
+
pa_mempool_stat stat;
};
assert(AO_load_acquire_read(&b->pool->stat.n_allocated) > 0);
assert(AO_load_acquire_read(&b->pool->stat.allocated_size) >= (AO_t) b->length);
-
+
AO_fetch_and_sub1_release_write(&b->pool->stat.n_allocated);
AO_fetch_and_add_release_write(&b->pool->stat.allocated_size, (AO_t) (-b->length));
if (b->type == PA_MEMBLOCK_IMPORTED) {
assert(AO_load_acquire_read(&b->pool->stat.n_imported) > 0);
assert(AO_load_acquire_read(&b->pool->stat.imported_size) >= (AO_t) b->length);
-
+
AO_fetch_and_sub1_release_write(&b->pool->stat.n_imported);
AO_fetch_and_add_release_write(&b->pool->stat.imported_size, (AO_t) (-b->length));
}
pa_memblock *pa_memblock_new(pa_mempool *p, size_t length) {
pa_memblock *b;
-
+
assert(p);
assert(length > 0);
-
+
if (!(b = pa_memblock_new_pool(p, length)))
b = memblock_new_appended(p, length);
if (!(slot = mempool_allocate_slot(p)))
return NULL;
-
+
b = mempool_slot_data(slot);
b->type = PA_MEMBLOCK_POOL;
b->data = (uint8_t*) b + sizeof(pa_memblock);
-
+
} else if (p->block_size - sizeof(struct mempool_slot) >= length) {
if (!(slot = mempool_allocate_slot(p)))
return NULL;
-
+
b = pa_xnew(pa_memblock, 1);
b->type = PA_MEMBLOCK_POOL_EXTERNAL;
b->data = mempool_slot_data(slot);
assert(d);
assert(length > 0);
assert(free_cb);
-
+
b = pa_xnew(pa_memblock, 1);
b->type = PA_MEMBLOCK_USER;
b->read_only = read_only;
if (PA_REFCNT_DEC(b) > 0)
return;
-
+
stat_remove(b);
switch (b->type) {
segment = b->per_type.imported.segment;
assert(segment);
assert(segment->import);
-
+
pa_hashmap_remove(segment->import->blocks, PA_UINT32_TO_PTR(b->per_type.imported.id));
segment->import->release_cb(segment->import, b->per_type.imported.id, segment->import->userdata);
if (-- segment->n_blocks <= 0)
segment_detach(segment);
-
+
pa_xfree(b);
break;
}
slot = mempool_slot_by_ptr(b->pool, b->data);
assert(slot);
-
+
PA_LLIST_PREPEND(struct mempool_slot, b->pool->free_slots, slot);
-
+
if (b->type == PA_MEMBLOCK_POOL_EXTERNAL)
pa_xfree(b);
if ((slot = mempool_allocate_slot(b->pool))) {
void *new_data;
/* We can move it into a local pool, perfect! */
-
+
b->type = PA_MEMBLOCK_POOL_EXTERNAL;
b->read_only = 0;
static void memblock_replace_import(pa_memblock *b) {
pa_memimport_segment *seg;
-
+
assert(b);
assert(b->type == PA_MEMBLOCK_IMPORTED);
if (p->block_size < ps)
p->block_size = ps;
-
+
p->n_blocks = PA_MEMPOOL_SLOTS_MAX;
assert(p->block_size > sizeof(struct mempool_slot));
}
p->n_init = 0;
-
+
PA_LLIST_HEAD_INIT(pa_memimport, p->imports);
PA_LLIST_HEAD_INIT(pa_memexport, p->exports);
PA_LLIST_HEAD_INIT(struct mempool_slot, p->free_slots);
if (AO_load_acquire_read(&p->stat.n_allocated) > 0)
pa_log_warn("WARNING! Memory pool destroyed but not all memory blocks freed!");
-
+
pa_shm_free(&p->memory);
pa_xfree(p);
}
void pa_mempool_vacuum(pa_mempool *p) {
struct mempool_slot *slot;
-
+
assert(p);
for (slot = p->free_slots; slot; slot = slot->next)
return -1;
*id = p->memory.id;
-
+
return 0;
}
assert(p);
assert(cb);
-
+
i = pa_xnew(pa_memimport, 1);
i->pool = p;
i->segments = pa_hashmap_new(NULL, NULL);
i->blocks = pa_hashmap_new(NULL, NULL);
i->release_cb = cb;
i->userdata = userdata;
-
+
PA_LLIST_PREPEND(pa_memimport, p->imports, i);
return i;
}
return NULL;
seg = pa_xnew(pa_memimport_segment, 1);
-
+
if (pa_shm_attach_ro(&seg->memory, shm_id) < 0) {
pa_xfree(seg);
return NULL;
seg->import = i;
seg->n_blocks = 0;
-
+
pa_hashmap_put(i->segments, PA_UINT32_TO_PTR(shm_id), seg);
return seg;
}
void pa_memimport_free(pa_memimport *i) {
pa_memexport *e;
pa_memblock *b;
-
+
assert(i);
/* If we've exported this block further we need to revoke that export */
pa_hashmap_free(i->blocks, NULL, NULL);
pa_hashmap_free(i->segments, NULL, NULL);
-
+
PA_LLIST_REMOVE(pa_memimport, i->pool->imports, i);
pa_xfree(i);
}
pa_memblock* pa_memimport_get(pa_memimport *i, uint32_t block_id, uint32_t shm_id, size_t offset, size_t size) {
pa_memblock *b;
pa_memimport_segment *seg;
-
+
assert(i);
if (pa_hashmap_size(i->blocks) >= PA_MEMIMPORT_SLOTS_MAX)
return NULL;
- if (!(seg = pa_hashmap_get(i->segments, PA_UINT32_TO_PTR(shm_id))))
+ if (!(seg = pa_hashmap_get(i->segments, PA_UINT32_TO_PTR(shm_id))))
if (!(seg = segment_attach(i, shm_id)))
return NULL;
if (offset+size > seg->memory.size)
return NULL;
-
+
b = pa_xnew(pa_memblock, 1);
b->type = PA_MEMBLOCK_IMPORTED;
b->read_only = 1;
pa_hashmap_put(i->blocks, PA_UINT32_TO_PTR(block_id), b);
seg->n_blocks++;
-
+
stat_add(b);
-
+
return b;
}
if (!(b = pa_hashmap_get(i->blocks, PA_UINT32_TO_PTR(id))))
return -1;
-
+
memblock_replace_import(b);
return 0;
}
/* For sending blocks to other nodes */
pa_memexport* pa_memexport_new(pa_mempool *p, pa_memexport_revoke_cb_t cb, void *userdata) {
pa_memexport *e;
-
+
assert(p);
assert(cb);
if (!p->memory.shared)
return NULL;
-
+
e = pa_xnew(pa_memexport, 1);
e->pool = p;
PA_LLIST_HEAD_INIT(struct memexport_slot, e->free_slots);
e->n_init = 0;
e->revoke_cb = cb;
e->userdata = userdata;
-
+
PA_LLIST_PREPEND(pa_memexport, p->exports, e);
return e;
}
assert(AO_load_acquire_read(&e->pool->stat.n_exported) > 0);
assert(AO_load_acquire_read(&e->pool->stat.exported_size) >= (AO_t) e->slots[id].block->length);
-
+
AO_fetch_and_sub1_release_write(&e->pool->stat.n_exported);
AO_fetch_and_add_release_write(&e->pool->stat.exported_size, (AO_t) -e->slots[id].block->length);
-
+
pa_memblock_unref(e->slots[id].block);
e->slots[id].block = NULL;
for (slot = e->used_slots; slot; slot = next) {
uint32_t idx;
next = slot->next;
-
+
if (slot->block->type != PA_MEMBLOCK_IMPORTED ||
slot->block->per_type.imported.segment->import != i)
continue;
assert(p);
assert(b);
-
+
if (b->type == PA_MEMBLOCK_IMPORTED ||
b->type == PA_MEMBLOCK_POOL ||
b->type == PA_MEMBLOCK_POOL_EXTERNAL) {
int pa_memexport_put(pa_memexport *e, pa_memblock *b, uint32_t *block_id, uint32_t *shm_id, size_t *offset, size_t * size) {
pa_shm *memory;
struct memexport_slot *slot;
-
+
assert(e);
assert(b);
assert(block_id);
assert(b->pool);
memory = &b->pool->memory;
}
-
+
assert(b->data >= memory->ptr);
assert((uint8_t*) b->data + b->length <= (uint8_t*) memory->ptr + memory->size);
-
+
*shm_id = memory->id;
*offset = (uint8_t*) b->data - (uint8_t*) memory->ptr;
*size = b->length;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
typedef enum pa_memblock_type {
PA_MEMBLOCK_POOL, /* Memory is part of the memory pool */
PA_MEMBLOCK_POOL_EXTERNAL, /* Data memory is part of the memory pool but the pa_memblock structure itself not */
- PA_MEMBLOCK_APPENDED, /* the data is appended to the memory block */
+ PA_MEMBLOCK_APPENDED, /* the data is appended to the memory block */
PA_MEMBLOCK_USER, /* User supplied memory, to be freed with free_cb */
PA_MEMBLOCK_FIXED, /* data is a pointer to fixed memory that needs not to be freed */
PA_MEMBLOCK_IMPORTED, /* Memory is imported from another process via shm */
struct {
void (*free_cb)(void *p); /* If type == PA_MEMBLOCK_USER this points to a function for freeing this memory block */
} user;
-
+
struct {
uint32_t id;
pa_memimport_segment *segment;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
size_t prebuf,
size_t minreq,
pa_memblock *silence) {
-
+
pa_memblockq* bq;
-
+
assert(base > 0);
assert(maxlength >= base);
-
+
bq = pa_xnew(pa_memblockq, 1);
bq->blocks = bq->blocks_tail = NULL;
bq->n_blocks = 0;
bq->prebuf = bq->maxlength;
bq->minreq = (minreq/base)*base;
-
+
if (bq->minreq > bq->tlength - bq->prebuf)
bq->minreq = bq->tlength - bq->prebuf;
if (!bq->minreq)
bq->minreq = 1;
-
+
pa_log_debug("memblockq sanitized: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu",
(unsigned long)bq->maxlength, (unsigned long)bq->tlength, (unsigned long)bq->base, (unsigned long)bq->prebuf, (unsigned long)bq->minreq);
bq->state = bq->prebuf ? PREBUF : RUNNING;
bq->silence = silence ? pa_memblock_ref(silence) : NULL;
bq->mcalign = NULL;
-
+
return bq;
}
if (bq->mcalign)
pa_mcalign_free(bq->mcalign);
-
+
pa_xfree(bq);
}
assert(q);
assert(bq->n_blocks >= 1);
-
+
if (q->prev)
q->prev->next = q->next;
else
bq->blocks = q->next;
-
+
if (q->next)
q->next->prev = q->prev;
else
}
int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
-
+
struct memblock_list *q, *n;
pa_memchunk chunk;
-
+
assert(bq);
assert(uchunk);
assert(uchunk->memblock);
return -1;
chunk = *uchunk;
-
+
if (bq->read_index > bq->write_index) {
/* We currently have a buffer underflow, we need to drop some
return 0;
}
}
-
+
/* We go from back to front to look for the right place to add
* this new entry. Drop data we will overwrite on the way */
assert(bq->write_index + (int64_t)chunk.length > q->index &&
bq->write_index + (int64_t)chunk.length < q->index + (int64_t)q->chunk.length &&
bq->write_index < q->index);
-
+
/* The job overwrites the current entry at the end, so let's drop the beginning of this entry */
d = bq->write_index + chunk.length - q->index;
q->index += d;
q->chunk.index += d;
q->chunk.length -= d;
-
+
q = q->prev;
}
-
+
}
if (q) {
assert(bq->write_index >= q->index + (int64_t)q->chunk.length);
assert(!q->next || (bq->write_index + (int64_t)chunk.length <= q->next->index));
-
+
/* Try to merge memory blocks */
-
+
if (q->chunk.memblock == chunk.memblock &&
q->chunk.index + (int64_t)q->chunk.length == chunk.index &&
bq->write_index == q->index + (int64_t)q->chunk.length) {
-
+
q->chunk.length += chunk.length;
bq->write_index += chunk.length;
return 0;
n->prev->next = n;
else
bq->blocks = n;
-
+
bq->n_blocks++;
return 0;
}
bq->state = PREBUF;
return -1;
}
-
+
/* Do we need to spit out silence? */
if (!bq->blocks || bq->blocks->index > bq->read_index) {
if (!length || length > chunk->memblock->length)
length = chunk->memblock->length;
-
+
chunk->length = length;
} else {
* the time to sleep */
if (!bq->blocks)
return -1;
-
+
chunk->memblock = NULL;
chunk->length = length;
}
/* Ok, let's pass real data to the caller */
assert(bq->blocks->index == bq->read_index);
-
+
*chunk = bq->blocks->chunk;
pa_memblock_ref(chunk->memblock);
assert(bq->blocks->index >= bq->read_index);
d = (size_t) (bq->blocks->index - bq->read_index);
-
+
if (d >= length) {
/* The first block is too far in the future */
-
+
bq->read_index += length;
break;
} else {
-
+
length -= d;
bq->read_index += d;
}
bq->read_index += length;
break;
}
-
+
} else {
/* The list is empty, there's nothing we could drop */
if (bq->prebuf > 0) {
size_t l = pa_memblockq_get_length(bq);
-
+
if (bq->state == PREBUF && l < bq->prebuf)
return 0;
if (length % bq->base)
return 0;
-
+
return pa_memblockq_get_length(bq) + length <= bq->tlength;
}
if (bq->write_index <= bq->read_index)
return 0;
-
+
return (size_t) (bq->write_index - bq->read_index);
}
void pa_memblockq_flush(pa_memblockq *bq) {
assert(bq);
-
+
while (bq->blocks)
drop_block(bq, bq->blocks);
size_t pa_memblockq_get_tlength(pa_memblockq *bq) {
assert(bq);
-
+
return bq->tlength;
}
assert(bq);
assert(chunk && bq->base);
-
+
if (bq->base == 1)
return pa_memblockq_push(bq, chunk);
-
+
if (!bq->mcalign)
bq->mcalign = pa_mcalign_new(bq->base);
if (!can_push(bq, pa_mcalign_csize(bq->mcalign, chunk->length)))
return -1;
-
+
pa_mcalign_push(bq->mcalign, chunk);
-
+
while (pa_mcalign_pop(bq->mcalign, &rchunk) >= 0) {
int r;
r = pa_memblockq_push(bq, &rchunk);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/* Parameters:
-
+
- idx: start value for both read and write index
- maxlength: maximum length of queue. If more data is pushed into
the queue, the operation will fail. Must not be 0.
-
+
- tlength: the target length of the queue. Pass 0 for the default.
-
+
- base: a base value for all metrics. Only multiples of this value
are popped from the queue or should be pushed into
it. Must not be 0.
-
+
- prebuf: If the queue runs empty wait until this many bytes are in
queue again before passing the first byte out. If set
to 0 pa_memblockq_pop() will return a silence memblock
if no data is in the queue and will never fail. Pass
(size_t) -1 for the default.
-
+
- minreq: pa_memblockq_missing() will only return values greater
than this value. Pass 0 for the default.
-
+
- silence: return this memblock whzen reading unitialized data
*/
pa_memblockq* pa_memblockq_new(
size_t maxlength,
size_t tlength,
size_t base,
- size_t prebuf,
+ size_t prebuf,
size_t minreq,
pa_memblock *silence);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
void pa_memchunk_make_writable(pa_memchunk *c, size_t min) {
pa_memblock *n;
size_t l;
-
+
assert(c);
assert(c->memblock);
assert(PA_REFCNT_VALUE(c->memblock) > 0);
l = c->length;
if (l < min)
l = min;
-
+
n = pa_memblock_new(c->memblock->pool, l);
memcpy(n->data, (uint8_t*) c->memblock->data + c->index, c->length);
pa_memblock_unref(c->memblock);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
return -1;
}
}
-
+
e = pa_xmalloc(sizeof(struct entry));
e->key = key;
e->value = value;
enum { WHITESPACE, KEY, VALUE_START, VALUE_SIMPLE, VALUE_DOUBLE_QUOTES, VALUE_TICKS } state;
const char *p, *key, *value;
size_t key_len = 0, value_len = 0;
-
+
key = value = NULL;
state = WHITESPACE;
for (p = args; *p; p++) {
if (map)
pa_modargs_free((pa_modargs*) map);
-
+
return NULL;
}
if (pa_atoi(v, value) < 0)
return -1;
-
+
return 0;
}
assert(ma && rss);
/* DEBUG_TRAP;*/
-
+
ss = *rss;
if ((pa_modargs_get_value_u32(ma, "rate", &ss.rate)) < 0)
return -1;
return -1;
*rss = ss;
-
+
return 0;
}
int pa_modargs_get_channel_map(pa_modargs *ma, pa_channel_map *rmap) {
pa_channel_map map;
const char *cm;
-
+
assert(ma);
assert(rmap);
int pa_modargs_get_sample_spec_and_channel_map(pa_modargs *ma, pa_sample_spec *rss, pa_channel_map *rmap, pa_channel_map_def_t def) {
pa_sample_spec ss;
pa_channel_map map;
-
+
assert(ma);
assert(rss);
assert(rmap);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_module* pa_module_load(pa_core *c, const char *name, const char *argument) {
pa_module *m = NULL;
int r;
-
+
assert(c && name);
if (c->disallow_module_loading)
goto fail;
-
+
m = pa_xmalloc(sizeof(pa_module));
m->name = pa_xstrdup(name);
m->argument = pa_xstrdup(argument);
-
+
if (!(m->dl = lt_dlopenext(name))) {
pa_log("Failed to open module \"%s\": %s", name, lt_dlerror());
goto fail;
pa_log("Failed to load module \"%s\": symbol \""PA_SYMBOL_DONE"\" not found.", name);
goto fail;
}
-
+
m->userdata = NULL;
m->core = c;
m->n_used = -1;
c->module_auto_unload_event = c->mainloop->time_new(c->mainloop, &ntv, timeout_callback, c);
}
assert(c->module_auto_unload_event);
-
+
assert(c->modules);
r = pa_idxset_put(c->modules, m, &m->index);
assert(r >= 0 && m->index != PA_IDXSET_INVALID);
- pa_log_info("Loaded \"%s\" (index: #%u; argument: \"%s\").", m->name, m->index, m->argument ? m->argument : "");
+ pa_log_info("Loaded \"%s\" (index: #%u; argument: \"%s\").", m->name, m->index, m->argument ? m->argument : "");
pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_NEW, m->index);
-
+
return m;
-
+
fail:
if (m) {
pa_xfree(m->argument);
pa_xfree(m->name);
-
+
if (m->dl)
lt_dlclose(m->dl);
if (m->core->disallow_module_loading)
return;
- pa_log_info("Unloading \"%s\" (index: #%u).", m->name, m->index);
+ pa_log_info("Unloading \"%s\" (index: #%u).", m->name, m->index);
m->done(m->core, m);
lt_dlclose(m->dl);
-
- pa_log_info("Unloaded \"%s\" (index: #%u).", m->name, m->index);
+
+ pa_log_info("Unloaded \"%s\" (index: #%u).", m->name, m->index);
pa_subscription_post(m->core, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_REMOVE, m->index);
-
+
pa_xfree(m->name);
pa_xfree(m->argument);
pa_xfree(m);
pa_module *m = p;
time_t *now = userdata;
assert(p && del && now);
-
+
if (m->n_used == 0 && m->auto_unload && m->last_used_time+m->core->module_idle_time <= *now) {
pa_module_free(m);
*del = 1;
if (!c->modules)
return;
-
+
time(&now);
pa_idxset_foreach(c->modules, unused_callback, &now);
}
if (m->n_used != used)
pa_subscription_post(m->core, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_CHANGE, m->index);
-
+
if (m->n_used != used && used == 0)
time(&m->last_used_time);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
uint32_t index;
lt_dlhandle dl;
-
+
int (*init)(pa_core *c, pa_module*m);
void (*done)(pa_core *c, pa_module*m);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
if (*name == 0)
return 0;
-
+
for (c = name; *c && (c-name < PA_NAME_MAX); c++)
if (!is_valid_char(*c))
return 0;
if (*c)
return 0;
-
+
return 1;
}
return NULL;
n = pa_xnew(char, strlen(name)+1);
-
+
for (a = name, b = n; *a && (a-name < PA_NAME_MAX); a++, b++)
*b = is_valid_char(*a) ? *a : '_';
void pa_namereg_free(pa_core *c) {
assert(c);
-
+
if (!c->namereg)
return;
-
+
assert(pa_hashmap_size(c->namereg) == 0);
pa_hashmap_free(c->namereg, NULL, NULL);
}
struct namereg_entry *e;
char *n = NULL;
int r;
-
+
assert(c);
assert(name);
assert(data);
if (!*name)
return NULL;
-
+
if ((type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE) &&
!is_valid_name(name) ) {
-
+
if (fail)
return NULL;
pa_xfree(n);
return NULL;
}
-
+
k = pa_xnew(char, l+4);
-
+
for (i = 2; i <= 99; i++) {
snprintf(k, l+4, "%s.%u", name, i);
pa_xfree(k);
return NULL;
}
-
+
pa_xfree(n);
n = k;
}
-
+
e = pa_xnew(struct namereg_entry, 1);
e->type = type;
e->name = n ? n : pa_xstrdup(name);
void pa_namereg_unregister(pa_core *c, const char *name) {
struct namereg_entry *e;
-
+
assert(c);
assert(name);
struct namereg_entry *e;
uint32_t idx;
assert(c);
-
+
if (!name) {
-
+
if (type == PA_NAMEREG_SOURCE)
name = pa_namereg_get_default_source_name(c);
else if (type == PA_NAMEREG_SINK)
name = pa_namereg_get_default_sink_name(c);
-
+
} else if (strcmp(name, "@DEFAULT_SINK@") == 0) {
if (type == PA_NAMEREG_SINK)
name = pa_namereg_get_default_sink_name(c);
-
+
} else if (strcmp(name, "@DEFAULT_SOURCE@") == 0) {
if (type == PA_NAMEREG_SOURCE)
name = pa_namereg_get_default_source_name(c);
-
+
} else if (strcmp(name, "@DEFAULT_MONITOR@") == 0) {
if (type == PA_NAMEREG_SOURCE) {
pa_sink *k;
-
+
if ((k = pa_namereg_get(c, NULL, PA_NAMEREG_SINK, autoload)))
return k->monitor_source;
}
if (!name)
return NULL;
-
+
if (c->namereg && (e = pa_hashmap_get(c->namereg, name)))
if (e->type == type)
return e->data;
if (autoload) {
pa_autoload_request(c, name, type);
-
+
if (c->namereg && (e = pa_hashmap_get(c->namereg, name)))
if (e->type == type)
return e->data;
}
-
+
return NULL;
}
int pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type) {
char **s;
-
+
assert(c);
assert(type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE);
if (!is_valid_name(name))
return -1;
-
+
pa_xfree(*s);
*s = pa_xstrdup(name);
pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SERVER|PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX);
const char *pa_namereg_get_default_sink_name(pa_core *c) {
pa_sink *s;
-
+
assert(c);
if (c->default_sink_name)
return c->default_sink_name;
-
+
if ((s = pa_idxset_first(c->sinks, NULL)))
pa_namereg_set_default(c, s->name, PA_NAMEREG_SINK);
const char *pa_namereg_get_default_source_name(pa_core *c) {
pa_source *s;
uint32_t idx;
-
+
assert(c);
if (c->default_source_name)
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
PA_COMMAND_FINISH_UPLOAD_STREAM,
PA_COMMAND_PLAY_SAMPLE,
PA_COMMAND_REMOVE_SAMPLE,
-
+
PA_COMMAND_GET_SERVER_INFO,
PA_COMMAND_GET_SINK_INFO,
PA_COMMAND_GET_SINK_INFO_LIST,
PA_COMMAND_GET_SAMPLE_INFO,
PA_COMMAND_GET_SAMPLE_INFO_LIST,
PA_COMMAND_SUBSCRIBE,
-
+
PA_COMMAND_SET_SINK_VOLUME,
PA_COMMAND_SET_SINK_INPUT_VOLUME,
PA_COMMAND_SET_SOURCE_VOLUME,
PA_COMMAND_SET_SINK_MUTE,
PA_COMMAND_SET_SOURCE_MUTE,
-
+
PA_COMMAND_CORK_PLAYBACK_STREAM,
PA_COMMAND_FLUSH_PLAYBACK_STREAM,
PA_COMMAND_TRIGGER_PLAYBACK_STREAM,
-
+
PA_COMMAND_SET_DEFAULT_SINK,
PA_COMMAND_SET_DEFAULT_SOURCE,
-
+
PA_COMMAND_SET_PLAYBACK_STREAM_NAME,
PA_COMMAND_SET_RECORD_STREAM_NAME,
-
+
PA_COMMAND_KILL_CLIENT,
PA_COMMAND_KILL_SINK_INPUT,
PA_COMMAND_KILL_SOURCE_OUTPUT,
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
assert(_r == 0); \
} while(0)
-static pa_mutex *global_mutex;
+static pa_mutex *global_mutex;
static pthread_once_t global_mutex_once = PTHREAD_ONCE_INIT;
-static void global_mutex_once_func(void) {
- global_mutex = pa_mutex_new(0);
-}
+static void global_mutex_once_func(void) {
+ global_mutex = pa_mutex_new(0);
+}
+
+void pa_once(pa_once_t *control, pa_once_func_t func) {
+ assert(control);
+ assert(func);
-void pa_once(pa_once_t *control, pa_once_func_t func) {
- assert(control);
- assert(func);
-
/* Create the global mutex */
- ASSERT_SUCCESS(pthread_once(&global_mutex_once, global_mutex_once_func));
+ ASSERT_SUCCESS(pthread_once(&global_mutex_once, global_mutex_once_func));
/* Create the local mutex */
- pa_mutex_lock(global_mutex);
+ pa_mutex_lock(global_mutex);
if (!control->mutex)
control->mutex = pa_mutex_new(1);
pa_mutex_unlock(global_mutex);
control->once_value = 1;
func();
}
- pa_mutex_unlock(control->mutex);
+ pa_mutex_unlock(control->mutex);
/* Caveat: We have to make sure that the once func has completed
* before returning, even if the once func is not actually
* executed by us. Hence the awkward locking. */
-}
+}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
control->once_value = 1;
func();
}
- pa_mutex_unlock(control->mutex);
+ pa_mutex_unlock(control->mutex);
/* Caveat: We have to make sure that the once func has completed
* before returning, even if the once func is not actually
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
p->length = length;
p->data = (uint8_t*) (p+1);
p->type = PA_PACKET_APPENDED;
-
+
return p;
}
p->length = length;
p->data = data;
p->type = PA_PACKET_DYNAMIC;
-
+
return p;
}
pa_packet* pa_packet_ref(pa_packet *p) {
assert(p);
assert(p->ref >= 1);
-
+
p->ref++;
return p;
}
void pa_packet_unref(pa_packet *p) {
assert(p);
assert(p->ref >= 1);
-
+
if (--p->ref == 0) {
if (p->type == PA_PACKET_DYNAMIC)
pa_xfree(p->data);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
*ret_port = atoi(e+2);
else if (e[1] != 0)
return NULL;
-
+
return pa_xstrndup(s+1, e-s-1);
} else {
char *e;
-
+
if (!(e = strrchr(s, ':')))
return pa_xstrdup(s);
if (*name == '{') {
char hn[256], *pfx;
/* The URL starts with a host specification for detecting local connections */
-
+
if (!pa_get_host_name(hn, sizeof(hn)))
return -1;
-
+
pfx = pa_sprintf_malloc("{%s}", hn);
if (!pa_startswith(name, pfx)) {
pa_xfree(pfx);
/* Not local */
return -1;
}
-
+
p = name + strlen(pfx);
pa_xfree(pfx);
} else
p = name;
-
+
if (*p == '/')
ret_p->type = PA_PARSED_ADDRESS_UNIX;
else if (pa_startswith(p, "unix:")) {
else
if (!(ret_p->path_or_host = parse_host(p, &ret_p->port)))
return -1;
-
-
+
+
return 0;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
if (r->time_event)
r->pdispatch->mainloop->time_free(r->time_event);
-
+
PA_LLIST_REMOVE(struct reply_info, r->pdispatch->replies, r);
-
+
pa_xfree(r);
}
assert(mainloop);
assert((entries && table) || (!entries && !table));
-
+
pd = pa_xmalloc(sizeof(pa_pdispatch));
pd->ref = 1;
pd->mainloop = mainloop;
pd->drain_callback = NULL;
pd->drain_userdata = NULL;
pd->creds = NULL;
-
+
return pd;
}
reply_info_free(pd->replies);
}
-
+
pa_xfree(pd);
}
assert(r);
pa_pdispatch_ref(pd);
-
+
callback = r->callback;
userdata = r->userdata;
tag = r->tag;
-
+
reply_info_free(r);
-
+
callback(pd, command, tag, ts, userdata);
if (pd->drain_callback && !pa_pdispatch_is_pending(pd))
assert(pd && packet && packet->data);
pa_pdispatch_ref(pd);
-
+
if (packet->length <= 8)
goto finish;
ts = pa_tagstruct_new(packet->data, packet->length);
assert(ts);
-
+
if (pa_tagstruct_getu32(ts, &command) < 0 ||
pa_tagstruct_getu32(ts, &tag) < 0)
goto finish;
-
+
#ifdef DEBUG_OPCODES
{
char t[256];
char const *p;
if (!(p = command_names[command]))
snprintf((char*) (p = t), sizeof(t), "%u", command);
-
+
pa_log("Recieved opcode <%s>", p);
}
#endif
}
ret = 0;
-
+
finish:
pd->creds = NULL;
-
+
if (ts)
pa_tagstruct_free(ts);
r->userdata = userdata;
r->free_cb = free_cb;
r->tag = tag;
-
+
pa_gettimeofday(&tv);
tv.tv_sec += timeout;
for (r = pd->replies; r; r = n) {
n = r->next;
- if (r->userdata == userdata)
+ if (r->userdata == userdata)
reply_info_free(r);
}
}
const pa_creds * pa_pdispatch_creds(pa_pdispatch *pd) {
assert(pd);
assert(pd->ref >= 1);
-
+
return pd->creds;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
if (r == 0)
return (pid_t) 0;
-
+
t[r] = 0;
if ((e = strchr(t, '\n')))
*e = 0;
static int open_pid_file(const char *fn, int mode) {
int fd = -1;
-
+
for (;;) {
struct stat st;
-
+
if ((fd = open(fn, mode, S_IRUSR|S_IWUSR)) < 0) {
if (mode != O_RDONLY || errno != ENOENT)
pa_log_warn("WARNING: failed to open PID file '%s': %s",
/* Try to lock the file. If that fails, go without */
if (pa_lock_fd(fd, 1) < 0)
goto fail;
-
+
if (fstat(fd, &st) < 0) {
pa_log_warn("WARNING: failed to fstat() PID file '%s': %s",
fn, pa_cstrerror(errno));
fn, pa_cstrerror(errno));
goto fail;
}
-
+
snprintf(t, sizeof(t), "%lu\n", (unsigned long) getpid());
l = strlen(t);
-
+
if (pa_loop_write(fd, t, l, NULL) != (ssize_t) l) {
pa_log("failed to write PID file.");
goto fail;
}
ret = 0;
-
+
fail:
if (fd >= 0) {
pa_lock_fd(fd, 0);
close(fd);
}
-
+
return ret;
}
}
ret = 0;
-
+
fail:
if (fd >= 0) {
if (!pid)
pid = &_pid;
-
+
pa_runtime_path("pid", fn, sizeof(fn));
-
+
if ((fd = open_pid_file(fn, O_RDONLY)) < 0)
goto fail;
-
+
if ((*pid = read_pid(fn, fd)) == (pid_t) -1)
goto fail;
ret = kill(*pid, sig);
-
+
fail:
-
+
if (fd >= 0) {
pa_lock_fd(fd, 0);
close(fd);
}
return ret;
-
+
}
#else /* OS_IS_WIN32 */
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
static void sink_input_drop(pa_sink_input *i, const pa_memchunk*chunk, size_t length) {
pa_memblockq *q;
-
+
assert(i);
assert(length > 0);
assert( i->userdata);
-
+
q = i->userdata;
pa_memblockq_drop(q, chunk, length);
const pa_channel_map *map,
pa_memblockq *q,
pa_cvolume *volume) {
-
+
pa_sink_input *si;
pa_sink_input_new_data data;
pa_sink_input_new_data_set_channel_map(&data, map);
pa_sink_input_new_data_set_sample_spec(&data, ss);
pa_sink_input_new_data_set_volume(&data, volume);
-
+
if (!(si = pa_sink_input_new(sink->core, &data, 0)))
return -1;
si->peek = sink_input_peek;
si->drop = sink_input_drop;
si->kill = sink_input_kill;
-
+
si->userdata = q;
pa_sink_notify(si->sink);
-
+
return 0;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
if (c->length <= 0)
return -1;
-
+
assert(c->memblock && c->memblock->length);
*chunk = *c;
pa_memblock_ref(c->memblock);
const pa_channel_map *map,
const pa_memchunk *chunk,
pa_cvolume *volume) {
-
+
pa_sink_input *si;
pa_memchunk *nchunk;
pa_sink_input_new_data data;
pa_sink_input_new_data_set_sample_spec(&data, ss);
pa_sink_input_new_data_set_channel_map(&data, map);
pa_sink_input_new_data_set_volume(&data, volume);
-
+
if (!(si = pa_sink_input_new(sink->core, &data, 0)))
return -1;
si->peek = sink_input_peek;
si->drop = sink_input_drop;
si->kill = sink_input_kill;
-
+
si->userdata = nchunk = pa_xnew(pa_memchunk, 1);
*nchunk = *chunk;
-
+
pa_memblock_ref(chunk->memblock);
pa_sink_notify(si->sink);
-
+
return 0;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
static pa_property* property_new(const char *name, void *data) {
pa_property* p;
assert(name && data);
-
+
p = pa_xmalloc(sizeof(pa_property));
p->name = pa_xstrdup(name);
p->data = data;
if (!(p = pa_hashmap_remove(c->properties, name)))
return -1;
-
+
property_free(p);
return 0;
}
pa_hashmap_free(c->properties, NULL, NULL);
c->properties = NULL;
-
+
}
void pa_property_dump(pa_core *c, pa_strbuf *s) {
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_iochannel_free(io);
return;
}
-
+
c = pa_cli_new(p->core, io, p->module);
assert(c);
pa_cli_set_eof_callback(c, cli_eof_cb, p);
p->connections = pa_idxset_new(NULL, NULL);
pa_socket_server_set_callback(p->server, on_connection, p);
-
+
return p;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_defer_event *defer_event;
char *original_name;
-
+
struct {
pa_memblock *current_memblock;
size_t memblock_index, fragment_size;
{ 3 * sizeof(int), esd_proto_stream_pan, "stream pan"},
{ 3 * sizeof(int), NULL, "sample pan" },
-
+
{ sizeof(int), NULL, "standby mode" },
{ 0, esd_proto_get_latency, "get latency" }
};
if (c->state == ESD_STREAMING_DATA)
c->protocol->n_player--;
-
+
pa_client_free(c->client);
if (c->sink_input) {
pa_sink_input_disconnect(c->sink_input);
pa_sink_input_unref(c->sink_input);
}
-
+
if (c->source_output) {
pa_source_output_disconnect(c->source_output);
pa_source_output_unref(c->source_output);
}
-
+
if (c->input_memblockq)
pa_memblockq_free(c->input_memblockq);
if (c->output_memblockq)
if (c->playback.current_memblock)
pa_memblock_unref(c->playback.current_memblock);
-
+
pa_xfree(c->read_data);
pa_xfree(c->write_data);
if (c->io)
pa_iochannel_free(c->io);
-
+
if (c->defer_event)
c->protocol->core->mainloop->defer_free(c->defer_event);
i = c->write_data_length;
c->write_data_length += length;
-
+
memcpy((char*)c->write_data + i, data, length);
}
static int format_native2esd(pa_sample_spec *ss) {
int format = 0;
-
+
format = (ss->format == PA_SAMPLE_U8) ? ESD_BITS8 : ESD_BITS16;
format |= (ss->channels >= 2) ? ESD_STEREO : ESD_MONO;
pa_sink_input_new_data sdata;
assert(c && length == (sizeof(int32_t)*2+ESD_NAME_MAX));
-
+
memcpy(&format, data, sizeof(int32_t));
format = MAYBE_INT32_SWAP(c->swap_byte_order, format);
data = (const char*)data + sizeof(int32_t);
utf8_name = pa_utf8_filter(name);
pa_client_set_name(c->client, utf8_name);
pa_xfree(utf8_name);
-
+
c->original_name = pa_xstrdup(name);
assert(!c->sink_input && !c->input_memblockq);
pa_sink_input_new_data_set_sample_spec(&sdata, &ss);
sdata.module = c->protocol->module;
sdata.client = c->client;
-
+
c->sink_input = pa_sink_input_new(c->protocol->core, &sdata, 0);
CHECK_VALIDITY(c->sink_input, "Failed to create sink input.");
- l = (size_t) (pa_bytes_per_second(&ss)*PLAYBACK_BUFFER_SECONDS);
+ l = (size_t) (pa_bytes_per_second(&ss)*PLAYBACK_BUFFER_SECONDS);
c->input_memblockq = pa_memblockq_new(
0,
l,
c->state = ESD_STREAMING_DATA;
c->protocol->n_player++;
-
+
return 0;
}
pa_source_output_new_data sdata;
assert(c && length == (sizeof(int32_t)*2+ESD_NAME_MAX));
-
+
memcpy(&format, data, sizeof(int32_t));
format = MAYBE_INT32_SWAP(c->swap_byte_order, format);
data = (const char*)data + sizeof(int32_t);
}
}
}
-
+
strncpy(name, data, sizeof(name));
name[sizeof(name)-1] = 0;
utf8_name = pa_utf8_filter(name);
pa_client_set_name(c->client, utf8_name);
pa_xfree(utf8_name);
-
+
c->original_name = pa_xstrdup(name);
assert(!c->output_memblockq && !c->source_output);
pa_source_output_new_data_set_sample_spec(&sdata, &ss);
sdata.module = c->protocol->module;
sdata.client = c->client;
-
+
c->source_output = pa_source_output_new(c->protocol->core, &sdata, 9);
CHECK_VALIDITY(c->source_output, "Failed to create source_output.");
- l = (size_t) (pa_bytes_per_second(&ss)*RECORD_BUFFER_SECONDS);
+ l = (size_t) (pa_bytes_per_second(&ss)*RECORD_BUFFER_SECONDS);
c->output_memblockq = pa_memblockq_new(
0,
l,
0,
NULL);
pa_iochannel_socket_set_sndbuf(c->io, l/RECORD_BUFFER_FRAGMENTS*2);
-
+
c->source_output->push = source_output_push_cb;
c->source_output->kill = source_output_kill_cb;
c->source_output->get_latency = source_output_get_latency_cb;
c->state = ESD_STREAMING_DATA;
c->protocol->n_player++;
-
+
return 0;
}
double usec = pa_sink_get_latency(sink);
latency = (int) ((usec*44100)/1000000);
}
-
+
latency = MAYBE_INT32_SWAP(c->swap_byte_order, latency);
connection_write(c, &latency, sizeof(int32_t));
return 0;
char terminator[sizeof(int32_t)*6+ESD_NAME_MAX];
assert(c && data && length == sizeof(int32_t));
-
+
if (esd_proto_server_info(c, request, data, length) < 0)
return -1;
continue;
assert(t >= k*2+s);
-
+
if (conn->sink_input) {
pa_cvolume volume = *pa_sink_input_get_volume(conn->sink_input);
rate = conn->sink_input->sample_spec.rate;
rvolume = (volume.values[1]*ESD_VOLUME_BASE)/PA_VOLUME_NORM;
format = format_native2esd(&conn->sink_input->sample_spec);
}
-
+
/* id */
id = MAYBE_INT32_SWAP(c->swap_byte_order, (int32_t) (conn->index+1));
connection_write(c, &id, sizeof(int32_t));
if (nsamples) {
pa_scache_entry *ce;
-
+
idx = PA_IDXSET_INVALID;
for (ce = pa_idxset_first(c->protocol->core->scache, &idx); ce; ce = pa_idxset_next(c->protocol->core->scache, &idx)) {
int32_t id, rate, lvolume, rvolume, format, len;
/* id */
id = MAYBE_INT32_SWAP(c->swap_byte_order, (int) (ce->index+1));
connection_write(c, &id, sizeof(int32_t));
-
+
/* name */
memset(name, 0, ESD_NAME_MAX); /* don't leak old data */
if (strncmp(ce->name, SCACHE_PREFIX, sizeof(SCACHE_PREFIX)-1) == 0)
else
snprintf(name, ESD_NAME_MAX, "native.%s", ce->name);
connection_write(c, name, ESD_NAME_MAX);
-
+
/* rate */
rate = MAYBE_UINT32_SWAP(c->swap_byte_order, ce->sample_spec.rate);
connection_write(c, &rate, sizeof(int32_t));
-
+
/* left */
lvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM);
connection_write(c, &lvolume, sizeof(int32_t));
-
+
/*right*/
rvolume = MAYBE_UINT32_SWAP(c->swap_byte_order, (ce->volume.values[0]*ESD_VOLUME_BASE)/PA_VOLUME_NORM);
connection_write(c, &rvolume, sizeof(int32_t));
-
+
/*format*/
format = MAYBE_INT32_SWAP(c->swap_byte_order, format_native2esd(&ce->sample_spec));
connection_write(c, &format, sizeof(int32_t));
struct connection *conn;
assert(c && data && length == sizeof(int32_t)*3);
-
+
memcpy(&idx, data, sizeof(uint32_t));
idx = MAYBE_UINT32_SWAP(c->swap_byte_order, idx) - 1;
data = (const char*)data + sizeof(uint32_t);
ok = 0;
connection_write(c, &ok, sizeof(int32_t));
-
+
return 0;
}
memcpy(&rate, data, sizeof(int32_t));
rate = MAYBE_INT32_SWAP(c->swap_byte_order, rate);
data = (const char*)data + sizeof(int32_t);
-
+
ss.rate = rate;
format_esd2native(format, c->swap_byte_order, &ss);
name[sizeof(name)-1] = 0;
CHECK_VALIDITY(pa_utf8_valid(name), "Invalid UTF8 in sample name.");
-
+
assert(!c->scache.memchunk.memblock);
c->scache.memchunk.memblock = pa_memblock_new(c->protocol->core->mempool, sc_length);
c->scache.memchunk.index = 0;
c->scache.sample_spec = ss;
assert(!c->scache.name);
c->scache.name = pa_xstrdup(name);
-
+
c->state = ESD_CACHING_SAMPLE;
pa_scache_add_item(c->protocol->core, c->scache.name, NULL, NULL, NULL, &idx);
idx += 1;
connection_write(c, &idx, sizeof(uint32_t));
-
+
return 0;
}
idx = MAYBE_UINT32_SWAP(c->swap_byte_order, idx) - 1;
ok = 0;
-
+
if ((name = pa_scache_get_name_by_id(c->protocol->core, idx))) {
if (request == ESD_PROTO_SAMPLE_PLAY) {
pa_sink *sink;
-
+
if ((sink = pa_namereg_get(c->protocol->core, c->protocol->sink_name, PA_NAMEREG_SINK, 1)))
if (pa_scache_play_item(c->protocol->core, name, sink, PA_VOLUME_NORM) >= 0)
ok = idx + 1;
ok = idx + 1;
}
}
-
+
connection_write(c, &ok, sizeof(int32_t));
return 0;
assert(c && c->io);
/* pa_log("READ"); */
-
+
if (c->state == ESD_NEXT_REQUEST) {
ssize_t r;
assert(c->read_data_length < sizeof(c->request));
if ((c->read_data_length+= r) >= sizeof(c->request)) {
struct proto_handler *handler;
-
+
c->request = MAYBE_INT32_SWAP(c->swap_byte_order, c->request);
if (c->request < ESD_PROTO_CONNECT || c->request > ESD_PROTO_MAX) {
pa_log("recieved unimplemented request #%u.", c->request);
return -1;
}
-
+
if (handler->data_length == 0) {
c->read_data_length = 0;
if (handler->proc(c, c->request, NULL, 0) < 0)
return -1;
-
+
} else {
if (c->read_data_alloc < handler->data_length)
c->read_data = pa_xrealloc(c->read_data, c->read_data_alloc = handler->data_length);
assert(c->read_data);
-
+
c->state = ESD_NEEDS_REQDATA;
c->read_data_length = 0;
}
struct proto_handler *handler = proto_map+c->request;
assert(handler->proc);
-
+
assert(c->read_data && c->read_data_length < handler->data_length);
if ((r = pa_iochannel_read(c->io, (uint8_t*) c->read_data + c->read_data_length, handler->data_length - c->read_data_length)) <= 0) {
c->state = ESD_NEXT_REQUEST;
c->read_data_length = 0;
-
+
if (handler->proc(c, c->request, c->read_data, l) < 0)
return -1;
}
ssize_t r;
assert(c->scache.memchunk.memblock && c->scache.name && c->scache.memchunk.index < c->scache.memchunk.length);
-
+
if ((r = pa_iochannel_read(c->io, (uint8_t*) c->scache.memchunk.memblock->data+c->scache.memchunk.index, c->scache.memchunk.length-c->scache.memchunk.index)) <= 0) {
pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
return -1;
c->scache.memchunk.index += r;
assert(c->scache.memchunk.index <= c->scache.memchunk.length);
-
+
if (c->scache.memchunk.index == c->scache.memchunk.length) {
uint32_t idx;
-
+
c->scache.memchunk.index = 0;
pa_scache_add_item(c->protocol->core, c->scache.name, &c->scache.sample_spec, NULL, &c->scache.memchunk, &idx);
idx += 1;
connection_write(c, &idx, sizeof(uint32_t));
}
-
+
} else if (c->state == ESD_STREAMING_DATA && c->sink_input) {
pa_memchunk chunk;
ssize_t r;
if (l > c->playback.fragment_size)
l = c->playback.fragment_size;
- if (c->playback.current_memblock)
+ if (c->playback.current_memblock)
if (c->playback.current_memblock->length - c->playback.memblock_index < l) {
pa_memblock_unref(c->playback.current_memblock);
c->playback.current_memblock = NULL;
c->playback.memblock_index = 0;
}
-
+
if (!c->playback.current_memblock) {
c->playback.current_memblock = pa_memblock_new(c->protocol->core->mempool, c->playback.fragment_size*2);
assert(c->playback.current_memblock && c->playback.current_memblock->length >= l);
pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
return -1;
}
-
+
chunk.memblock = c->playback.current_memblock;
chunk.index = c->playback.memblock_index;
chunk.length = r;
assert(chunk.memblock);
c->playback.memblock_index += r;
-
+
assert(c->input_memblockq);
pa_memblockq_push_align(c->input_memblockq, &chunk);
assert(c->sink_input);
pa_sink_notify(c->sink_input->sink);
}
-
+
return 0;
}
assert(c && c->io);
/* pa_log("WRITE"); */
-
+
if (c->write_data_length) {
ssize_t r;
-
+
assert(c->write_data_index < c->write_data_length);
if ((r = pa_iochannel_write(c->io, (uint8_t*) c->write_data+c->write_data_index, c->write_data_length-c->write_data_index)) < 0) {
pa_log("write(): %s", pa_cstrerror(errno));
return -1;
}
-
+
if ((c->write_data_index +=r) >= c->write_data_length)
c->write_data_length = c->write_data_index = 0;
-
+
} else if (c->state == ESD_STREAMING_DATA && c->source_output) {
pa_memchunk chunk;
ssize_t r;
assert(c->output_memblockq);
if (pa_memblockq_peek(c->output_memblockq, &chunk) < 0)
return 0;
-
+
assert(chunk.memblock && chunk.length);
-
+
if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) {
pa_memblock_unref(chunk.memblock);
pa_log("write(): %s", pa_cstrerror(errno));
pa_source_notify(c->source_output->source);
}
-
+
return 0;
}
if (pa_iochannel_is_writable(c->io))
if (do_write(c) < 0)
goto fail;
-
+
return;
fail:
assert(a && c && c->defer_event == e);
/* pa_log("DEFER"); */
-
+
do_work(c);
}
struct connection*c;
assert(i && i->userdata && chunk);
c = i->userdata;
-
+
if (pa_memblockq_peek(c->input_memblockq, chunk) < 0) {
if (c->dead)
connection_free(c);
-
+
return -1;
}
assert(i && c && length);
/* pa_log("DROP"); */
-
+
pa_memblockq_drop(c->input_memblockq, chunk, length);
/* do something */
pa_iochannel_free(io);
return;
}
-
+
c = pa_xnew(struct connection, 1);
c->protocol = p;
c->io = io;
c->client->owner = p->module;
c->client->kill = client_kill_cb;
c->client->userdata = c;
-
+
c->authorized = !!p->public;
c->swap_byte_order = 0;
c->dead = 0;
c->auth_timeout_event = p->core->mainloop->time_new(p->core->mainloop, &tv, auth_timeout, c);
} else
c->auth_timeout_event = NULL;
-
+
c->defer_event = p->core->mainloop->defer_new(p->core->mainloop, defer_callback, c);
assert(c->defer_event);
p->core->mainloop->defer_enable(c->defer_event, 0);
pa_protocol_esound *p;
int public = 0;
const char *acl;
-
+
assert(core);
assert(server);
assert(m);
}
} else
p->auth_ip_acl = NULL;
-
+
p->module = m;
p->public = public;
p->server = server;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
assert(msg);
assert(mime);
- snprintf(s, sizeof(s),
+ snprintf(s, sizeof(s),
"HTTP/1.0 %i %s\n"
"Connection: close\n"
"Content-Type: %s\n"
}
case MIME_HEADER: {
-
+
/* Ignore MIME headers */
if (strcspn(s, " \r\n") != 0)
break;
-
+
/* We're done */
c->state = DATA;
pa_log_info("request for %s", c->url);
-
+
if (!strcmp(c->url, URL_ROOT)) {
char txt[256];
http_response(c, 200, "OK", "text/html");
PRINTF_FIELD("Default Sample Specification:", pa_sample_spec_snprint(txt, sizeof(txt), &c->protocol->core->default_sample_spec));
PRINTF_FIELD("Default Sink:", pa_namereg_get_default_sink_name(c->protocol->core));
PRINTF_FIELD("Default Source:", pa_namereg_get_default_source_name(c->protocol->core));
-
+
pa_ioline_puts(c->line, "</table>");
pa_ioline_puts(c->line, "<p><a href=\"/status\">Click here</a> for an extensive server status report.</p>");
-
+
pa_ioline_puts(c->line, "</body></html>\n");
-
- pa_ioline_defer_close(c->line);
+
+ pa_ioline_defer_close(c->line);
} else if (!strcmp(c->url, URL_CSS)) {
http_response(c, 200, "OK", "text/css");
- pa_ioline_puts(c->line,
+ pa_ioline_puts(c->line,
"body { color: black; background-color: white; margin: 0.5cm; }\n"
"a:link, a:visited { color: #900000; }\n"
"p { margin-left: 0.5cm; margin-right: 0.5cm; }\n"
break;
}
-
+
default:
;
}
return;
-
+
fail:
internal_server_error(c);
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
[PA_COMMAND_SET_SINK_VOLUME] = command_set_volume,
[PA_COMMAND_SET_SINK_INPUT_VOLUME] = command_set_volume,
[PA_COMMAND_SET_SOURCE_VOLUME] = command_set_volume,
-
+
[PA_COMMAND_SET_SINK_MUTE] = command_set_mute,
[PA_COMMAND_SET_SOURCE_MUTE] = command_set_mute,
[PA_COMMAND_FLUSH_PLAYBACK_STREAM] = command_flush_playback_stream,
[PA_COMMAND_TRIGGER_PLAYBACK_STREAM] = command_trigger_or_prebuf_playback_stream,
[PA_COMMAND_PREBUF_PLAYBACK_STREAM] = command_trigger_or_prebuf_playback_stream,
-
+
[PA_COMMAND_CORK_RECORD_STREAM] = command_cork_record_stream,
[PA_COMMAND_FLUSH_RECORD_STREAM] = command_flush_record_stream,
-
+
[PA_COMMAND_SET_DEFAULT_SINK] = command_set_default_sink_or_source,
[PA_COMMAND_SET_DEFAULT_SOURCE] = command_set_default_sink_or_source,
- [PA_COMMAND_SET_PLAYBACK_STREAM_NAME] = command_set_stream_name,
+ [PA_COMMAND_SET_PLAYBACK_STREAM_NAME] = command_set_stream_name,
[PA_COMMAND_SET_RECORD_STREAM_NAME] = command_set_stream_name,
[PA_COMMAND_KILL_CLIENT] = command_kill,
[PA_COMMAND_KILL_SINK_INPUT] = command_kill,
const pa_sample_spec *ss,
const pa_channel_map *map,
const char *name, size_t length) {
-
+
struct upload_stream *s;
assert(c && ss && name && length);
-
+
s = pa_xnew(struct upload_stream, 1);
s->type = UPLOAD_STREAM;
s->connection = c;
s->memchunk.length = 0;
s->length = length;
-
+
pa_idxset_put(c->output_streams, s, &s->index);
return s;
}
pa_idxset_remove_by_data(o->connection->output_streams, o, NULL);
pa_xfree(o->name);
-
+
if (o->memchunk.memblock)
pa_memblock_unref(o->memchunk.memblock);
-
+
pa_xfree(o);
}
const char *name,
size_t maxlength,
size_t fragment_size) {
-
+
struct record_stream *s;
pa_source_output *source_output;
size_t base;
pa_source_output_new_data data;
-
+
assert(c && ss && name && maxlength);
pa_source_output_new_data_init(&data);
pa_source_output_new_data_set_channel_map(&data, map);
data.module = c->protocol->module;
data.client = c->client;
-
+
if (!(source_output = pa_source_output_new(c->protocol->core, &data, 0)))
return NULL;
size_t minreq,
pa_cvolume *volume,
uint32_t syncid) {
-
+
struct playback_stream *s, *ssync;
pa_sink_input *sink_input;
pa_memblock *silence;
uint32_t idx;
int64_t start_index;
pa_sink_input_new_data data;
-
+
assert(c && ss && name && maxlength);
/* Find syncid group */
for (ssync = pa_idxset_first(c->output_streams, &idx); ssync; ssync = pa_idxset_next(c->output_streams, &idx)) {
-
+
if (ssync->type != PLAYBACK_STREAM)
continue;
if (!(sink_input = pa_sink_input_new(c->protocol->core, &data, 0)))
return NULL;
-
+
s = pa_xnew(struct playback_stream, 1);
s->type = PLAYBACK_STREAM;
s->connection = c;
s->syncid = syncid;
s->sink_input = sink_input;
s->underrun = 1;
-
+
s->sink_input->peek = sink_input_peek_cb;
s->sink_input->drop = sink_input_drop_cb;
s->sink_input->kill = sink_input_kill_cb;
PA_LLIST_INIT(struct playback_stream, s);
start_index = 0;
}
-
+
silence = pa_silence_memblock_new(c->protocol->core->mempool, ss, 0);
-
+
s->memblockq = pa_memblockq_new(
start_index,
maxlength,
silence);
pa_memblock_unref(silence);
-
+
s->requested_bytes = 0;
s->drain_request = 0;
-
+
pa_idxset_put(c->output_streams, s, &s->index);
return s;
if (c->auth_timeout_event)
c->protocol->core->mainloop->time_free(c->auth_timeout_event);
-
+
pa_xfree(c);
}
if (!(l = pa_memblockq_missing(s->memblockq)))
return;
-
+
if (l <= s->requested_bytes)
return;
if (l < pa_memblockq_get_minreq(s->memblockq))
return;
-
+
s->requested_bytes += l;
t = pa_tagstruct_new(NULL, 0);
start = PA_IDXSET_INVALID;
for (;;) {
pa_memchunk chunk;
-
+
if (!(r = pa_idxset_rrobin(c->record_streams, &c->rrobin_index)))
return;
if (pa_memblockq_peek(r->memblockq, &chunk) >= 0) {
pa_memchunk schunk = chunk;
-
+
if (schunk.length > r->fragment_size)
schunk.length = r->fragment_size;
pa_pstream_send_memblock(c->pstream, r->index, 0, PA_SEEK_RELATIVE, &schunk);
pa_memblockq_drop(r->memblockq, &chunk, schunk.length);
pa_memblock_unref(schunk.memblock);
-
+
return;
}
}
s->underrun = 1;
}
-
+
if (pa_memblockq_peek(s->memblockq, chunk) < 0) {
/* pa_log("peek: failure"); */
return -1;
}
/* pa_log("peek: %u", chunk->length); */
-
+
return 0;
}
s = i->userdata;
/*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
-
+
return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &s->sink_input->sample_spec);
}
struct record_stream *s;
assert(o && o->userdata && chunk);
s = o->userdata;
-
+
if (pa_memblockq_push_align(s->memblockq, chunk) < 0) {
pa_log_warn("Failed to push data into output queue.");
return;
- }
-
+ }
+
if (!pa_pstream_is_pending(s->connection->pstream))
send_memblock(s->connection);
}
s = o->userdata;
/*pa_log("get_latency: %u", pa_memblockq_get_length(s->memblockq));*/
-
+
return pa_bytes_to_usec(pa_memblockq_get_length(s->memblockq), &o->sample_spec);
}
static pa_tagstruct *reply_new(uint32_t tag) {
pa_tagstruct *reply;
-
+
reply = pa_tagstruct_new(NULL, 0);
pa_tagstruct_putu32(reply, PA_COMMAND_REPLY);
pa_tagstruct_putu32(reply, tag);
pa_sink *sink = NULL;
pa_cvolume volume;
int corked;
-
+
assert(c && t && c->protocol && c->protocol->core);
-
+
if (pa_tagstruct_get(
t,
PA_TAG_STRING, &name,
CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
pa_sink_input_cork(s->sink_input, corked);
-
+
reply = reply_new(tag);
pa_tagstruct_putu32(reply, s->index);
assert(s->sink_input);
pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_prebuf(s->memblockq));
pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_minreq(s->memblockq));
}
-
+
pa_pstream_send_tagstruct(c->pstream, reply);
request_bytes(s);
}
struct connection *c = userdata;
uint32_t channel;
assert(c && t);
-
+
if (pa_tagstruct_getu32(t, &channel) < 0 ||
!pa_tagstruct_eof(t)) {
protocol_error(c);
upload_stream_free(s);
}
-
+
pa_pstream_send_simple_ack(c->pstream, tag);
}
pa_source *source = NULL;
int corked;
assert(c && t && c->protocol && c->protocol->core);
-
+
if (pa_tagstruct_gets(t, &name) < 0 ||
pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
pa_tagstruct_get_channel_map(t, &map) < 0 ||
} else if (source_name) {
source = pa_namereg_get(c->protocol->core, source_name, PA_NAMEREG_SOURCE, 1);
CHECK_VALIDITY(c->pstream, source, tag, PA_ERR_NOENTITY);
- }
-
+ }
+
s = record_stream_new(c, source, &ss, &map, name, maxlength, fragment_size);
CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
-
+
pa_source_output_cork(s->source_output, corked);
-
+
reply = reply_new(tag);
pa_tagstruct_putu32(reply, s->index);
assert(s->source_output);
pa_tagstruct_putu32(reply, (uint32_t) pa_memblockq_get_maxlength(s->memblockq));
pa_tagstruct_putu32(reply, (uint32_t) s->fragment_size);
}
-
+
pa_pstream_send_tagstruct(c->pstream, reply);
}
static void command_exit(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
struct connection *c = userdata;
assert(c && t);
-
+
if (!pa_tagstruct_eof(t)) {
protocol_error(c);
return;
}
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
-
+
assert(c->protocol && c->protocol->core && c->protocol->core->mainloop);
c->protocol->core->mainloop->quit(c->protocol->core->mainloop, 0);
pa_pstream_send_simple_ack(c->pstream, tag); /* nonsense */
if (!c->authorized) {
int success = 0;
-
+
#ifdef HAVE_CREDS
const pa_creds *creds;
pa_log_warn("failed to get GID of group '%s'", c->protocol->auth_group);
else if (gid == creds->gid)
success = 1;
-
+
if (!success) {
if ((r = pa_uid_in_group(creds->uid, c->protocol->auth_group)) < 0)
pa_log_warn("failed to check group membership.");
success = 1;
}
}
-
+
pa_log_info("Got credentials: uid=%lu gid=%lu success=%i",
(unsigned long) creds->uid,
(unsigned long) creds->gid,
pa_pstream_use_shm(c->pstream, 1);
pa_log_info("Enabled SHM for new connection");
}
-
+
}
#endif
pa_pstream_send_error(c->pstream, tag, PA_ERR_ACCESS);
return;
}
-
+
c->authorized = 1;
if (c->auth_timeout_event) {
c->protocol->core->mainloop->time_free(c->auth_timeout_event);
#ifdef HAVE_CREDS
{
/* SHM support is only enabled after both sides made sure they are the same user. */
-
+
pa_creds ucred;
ucred.uid = getuid();
ucred.gid = getgid();
-
+
pa_pstream_send_tagstruct_with_creds(c->pstream, reply, &ucred);
}
#else
}
CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
-
+
pa_client_set_name(c->client, name);
pa_pstream_send_simple_ack(c->pstream, tag);
}
s = pa_idxset_get_by_index(c->output_streams, idx);
CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY);
-
+
s->drain_request = 0;
pa_memblockq_prebuf_disable(s->memblockq);
-
+
if (!pa_memblockq_is_readable(s->memblockq)) {
/* pa_log("immediate drain: %u", pa_memblockq_get_length(s->memblockq)); */
pa_pstream_send_simple_ack(c->pstream, tag);
pa_sink_notify(s->sink_input->sink);
}
-}
+}
static void command_stat(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
struct connection *c = userdata;
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
stat = pa_mempool_get_stat(c->protocol->core->mempool);
-
+
reply = reply_new(tag);
pa_tagstruct_putu32(reply, (uint32_t) AO_load_acquire_read((AO_t*) &stat->n_allocated));
pa_tagstruct_putu32(reply, (uint32_t) AO_load_acquire_read((AO_t*) &stat->allocated_size));
uint32_t idx;
pa_usec_t latency;
assert(c && t);
-
+
if (pa_tagstruct_getu32(t, &idx) < 0 ||
pa_tagstruct_get_timeval(t, &tv) < 0 ||
!pa_tagstruct_eof(t)) {
if (s->sink_input->resampled_chunk.memblock)
latency += pa_bytes_to_usec(s->sink_input->resampled_chunk.length, &s->sink_input->sample_spec);
pa_tagstruct_put_usec(reply, latency);
-
+
pa_tagstruct_put_usec(reply, 0);
pa_tagstruct_put_boolean(reply, s->sink_input->state == PA_SINK_INPUT_RUNNING);
pa_tagstruct_put_timeval(reply, &tv);
pa_channel_map map;
pa_tagstruct *reply;
assert(c && t && c->protocol && c->protocol->core);
-
- if (pa_tagstruct_gets(t, &name) < 0 ||
+
+ if (pa_tagstruct_gets(t, &name) < 0 ||
pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
pa_tagstruct_get_channel_map(t, &map) < 0 ||
pa_tagstruct_getu32(t, &length) < 0 ||
CHECK_VALIDITY(c->pstream, (length % pa_frame_size(&ss)) == 0 && length > 0, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, length <= PA_SCACHE_ENTRY_SIZE_MAX, tag, PA_ERR_TOOLARGE);
CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
-
+
s = upload_stream_new(c, &ss, &map, name, length);
CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_INVALID);
-
+
reply = reply_new(tag);
pa_tagstruct_putu32(reply, s->index);
pa_tagstruct_putu32(reply, length);
struct upload_stream *s;
uint32_t idx;
assert(c && t);
-
+
if (pa_tagstruct_getu32(t, &channel) < 0 ||
!pa_tagstruct_eof(t)) {
protocol_error(c);
pa_pstream_send_error(c->pstream, tag, PA_ERR_INTERNAL);
else
pa_pstream_send_simple_ack(c->pstream, tag);
-
+
upload_stream_free(s);
}
protocol_error(c);
return;
}
-
+
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
CHECK_VALIDITY(c->pstream, sink_index != PA_INVALID_INDEX || !sink_name || (*sink_name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
source = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SOURCE, 1);
} else if (command == PA_COMMAND_GET_CLIENT_INFO)
client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
- else if (command == PA_COMMAND_GET_MODULE_INFO)
+ else if (command == PA_COMMAND_GET_MODULE_INFO)
module = pa_idxset_get_by_index(c->protocol->core->modules, idx);
else if (command == PA_COMMAND_GET_SINK_INPUT_INFO)
si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
else
sce = pa_namereg_get(c->protocol->core, name, PA_NAMEREG_SAMPLE, 0);
}
-
+
if (!sink && !source && !client && !module && !si && !so && !sce) {
pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY);
return;
module_fill_tagstruct(reply, p);
else if (command == PA_COMMAND_GET_SINK_INPUT_INFO_LIST)
sink_input_fill_tagstruct(reply, p);
- else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
+ else if (command == PA_COMMAND_GET_SOURCE_OUTPUT_INFO_LIST)
source_output_fill_tagstruct(reply, p);
else {
assert(command == PA_COMMAND_GET_SAMPLE_INFO_LIST);
}
}
}
-
+
pa_pstream_send_tagstruct(c->pstream, reply);
}
protocol_error(c);
return;
}
-
+
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
reply = reply_new(tag);
pa_tagstruct_puts(reply, n);
pa_tagstruct_putu32(reply, c->protocol->core->cookie);
-
+
pa_pstream_send_tagstruct(c->pstream, reply);
}
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
CHECK_VALIDITY(c->pstream, (m & ~PA_SUBSCRIPTION_MASK_ALL) == 0, tag, PA_ERR_INVALID);
-
+
if (c->subscription)
pa_subscription_free(c->subscription);
uint32_t tag,
pa_tagstruct *t,
void *userdata) {
-
+
struct connection *c = userdata;
uint32_t idx;
pa_cvolume volume;
protocol_error(c);
return;
}
-
+
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, pa_cvolume_valid(&volume), tag, PA_ERR_INVALID);
uint32_t tag,
pa_tagstruct *t,
void *userdata) {
-
+
struct connection *c = userdata;
uint32_t idx;
int mute;
protocol_error(c);
return;
}
-
+
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
pa_sink_input_cork(ssync->sink_input, b);
pa_memblockq_prebuf_force(ssync->memblockq);
}
-
+
pa_pstream_send_simple_ack(c->pstream, tag);
-}
+}
static void command_flush_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
struct connection *c = userdata;
pa_memblockq_flush(s->memblockq);
s->underrun = 0;
-
+
/* Do the same for all other members in the sync group */
for (ssync = s->prev; ssync; ssync = ssync->prev) {
pa_memblockq_flush(ssync->memblockq);
pa_memblockq_flush(ssync->memblockq);
ssync->underrun = 0;
}
-
+
pa_pstream_send_simple_ack(c->pstream, tag);
pa_sink_notify(s->sink_input->sink);
request_bytes(s);
-
+
for (ssync = s->prev; ssync; ssync = ssync->prev)
request_bytes(ssync);
case PA_COMMAND_PREBUF_PLAYBACK_STREAM:
pa_memblockq_prebuf_force(s->memblockq);
break;
-
+
case PA_COMMAND_TRIGGER_PLAYBACK_STREAM:
pa_memblockq_prebuf_disable(s->memblockq);
break;
-
+
default:
abort();
}
protocol_error(c);
return;
}
-
+
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
CHECK_VALIDITY(c->pstream, name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
if (command == PA_COMMAND_SET_PLAYBACK_STREAM_NAME) {
struct playback_stream *s;
-
+
s = pa_idxset_get_by_index(c->output_streams, idx);
CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
CHECK_VALIDITY(c->pstream, s->type == PLAYBACK_STREAM, tag, PA_ERR_NOENTITY);
pa_sink_input_set_name(s->sink_input, name);
-
+
} else {
struct record_stream *s;
-
+
s = pa_idxset_get_by_index(c->record_streams, idx);
CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
if (command == PA_COMMAND_KILL_CLIENT) {
pa_client *client;
-
+
client = pa_idxset_get_by_index(c->protocol->core->clients, idx);
CHECK_VALIDITY(c->pstream, client, tag, PA_ERR_NOENTITY);
pa_client_kill(client);
-
+
} else if (command == PA_COMMAND_KILL_SINK_INPUT) {
pa_sink_input *s;
-
+
s = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
pa_source_output *s;
assert(command == PA_COMMAND_KILL_SOURCE_OUTPUT);
-
+
s = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
CHECK_VALIDITY(c->pstream, s, tag, PA_ERR_NOENTITY);
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name) && !strchr(name, '/'), tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, !argument || pa_utf8_valid(argument), tag, PA_ERR_INVALID);
-
+
if (!(m = pa_module_load(c->protocol->core, name, argument))) {
pa_pstream_send_error(c->pstream, tag, PA_ERR_MODINITFAILED);
return;
protocol_error(c);
return;
}
-
+
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
m = pa_idxset_get_by_index(c->protocol->core->modules, idx);
CHECK_VALIDITY(c->pstream, m, tag, PA_ERR_NOENTITY);
pa_tagstruct *reply;
assert(c && t);
- if (pa_tagstruct_gets(t, &name) < 0 ||
- pa_tagstruct_getu32(t, &type) < 0 ||
- pa_tagstruct_gets(t, &module) < 0 ||
+ if (pa_tagstruct_gets(t, &name) < 0 ||
+ pa_tagstruct_getu32(t, &type) < 0 ||
+ pa_tagstruct_gets(t, &module) < 0 ||
pa_tagstruct_gets(t, &argument) < 0 ||
!pa_tagstruct_eof(t)) {
protocol_error(c);
return;
}
-
+
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
CHECK_VALIDITY(c->pstream, name && *name && pa_utf8_valid(name), tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, type == 0 || type == 1, tag, PA_ERR_INVALID);
protocol_error(c);
return;
}
-
+
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
CHECK_VALIDITY(c->pstream, name || idx != PA_IDXSET_INVALID, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, !name || (*name && pa_utf8_valid(name) && (type == 0 || type == 1)), tag, PA_ERR_INVALID);
- if (name)
+ if (name)
r = pa_autoload_remove_by_name(c->protocol->core, name, type == 0 ? PA_NAMEREG_SINK : PA_NAMEREG_SOURCE);
else
r = pa_autoload_remove_by_index(c->protocol->core, idx);
protocol_error(c);
return;
}
-
+
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
reply = reply_new(tag);
while ((a = pa_hashmap_iterate(c->protocol->core->autoload_hashmap, &state, NULL)))
autoload_fill_tagstruct(reply, a);
}
-
+
pa_pstream_send_tagstruct(c->pstream, reply);
}
struct connection *c = userdata;
uint32_t idx = PA_INVALID_INDEX, idx_device = PA_INVALID_INDEX;
const char *name = NULL;
-
+
assert(c);
assert(t);
protocol_error(c);
return;
}
-
+
CHECK_VALIDITY(c->pstream, c->authorized, tag, PA_ERR_ACCESS);
CHECK_VALIDITY(c->pstream, idx != PA_INVALID_INDEX, tag, PA_ERR_INVALID);
CHECK_VALIDITY(c->pstream, idx_device != PA_INVALID_INDEX || !name || (*name && pa_utf8_valid(name)), tag, PA_ERR_INVALID);
pa_sink *sink = NULL;
si = pa_idxset_get_by_index(c->protocol->core->sink_inputs, idx);
-
+
if (idx_device != PA_INVALID_INDEX)
sink = pa_idxset_get_by_index(c->protocol->core->sinks, idx_device);
else
pa_source *source;
so = pa_idxset_get_by_index(c->protocol->core->source_outputs, idx);
-
+
if (idx_device != PA_INVALID_INDEX)
source = pa_idxset_get_by_index(c->protocol->core->sources, idx_device);
else
return;
}
}
-
+
pa_pstream_send_simple_ack(c->pstream, tag);
-
+
}
/*** pstream callbacks ***/
struct connection *c = userdata;
struct output_stream *stream;
assert(p && chunk && userdata);
-
+
if (!(stream = pa_idxset_get_by_index(c->output_streams, channel))) {
pa_log("client sent block for invalid stream.");
/* Ignoring */
if (pa_memblockq_push_align(ps->memblockq, chunk) < 0) {
pa_tagstruct *t;
-
+
pa_log_warn("failed to push data into queue");
/* Pushing this block into the queue failed, so we simulate
* it by skipping ahead */
-
+
pa_memblockq_seek(ps->memblockq, chunk->length, PA_SEEK_RELATIVE);
/* Notify the user */
}
ps->underrun = 0;
-
+
pa_sink_notify(ps->sink_input->sink);
} else {
u->memchunk.index = u->memchunk.length = 0;
}
}
-
+
assert(u->memchunk.memblock);
-
- l = u->length;
+
+ l = u->length;
if (l > chunk->length)
l = chunk->length;
pa_log_info("Client authenticated by IP ACL.");
c->authorized = 1;
}
-
+
if (!c->authorized) {
struct timeval tv;
pa_gettimeofday(&tv);
c->client->kill = client_kill_cb;
c->client->userdata = c;
c->client->owner = p->module;
-
+
c->pstream = pa_pstream_new(p->core->mainloop, io, p->core->mempool);
assert(c->pstream);
#ifdef HAVE_CREDS
if (pa_iochannel_creds_supported(io))
pa_iochannel_creds_enable(io);
-
+
#endif
}
assert(p);
p->auth_cookie_in_property = 0;
-
+
if (!fn && pa_authkey_prop_get(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0) {
pa_log_info("using already loaded auth cookie.");
pa_authkey_prop_ref(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME);
p->auth_cookie_in_property = 1;
return 0;
}
-
+
if (!fn)
fn = PA_NATIVE_COOKIE_FILE;
if (pa_authkey_prop_put(p->core, PA_NATIVE_COOKIE_PROPERTY_NAME, p->auth_cookie, sizeof(p->auth_cookie)) >= 0)
p->auth_cookie_in_property = 1;
-
+
return 0;
}
pa_protocol_native *p;
int public = 0;
const char *acl;
-
+
assert(c);
assert(ma);
pa_log("auth-anonymous= expects a boolean argument.");
return NULL;
}
-
+
p = pa_xnew(pa_protocol_native, 1);
p->core = c;
p->module = m;
p->public = public;
p->server = NULL;
p->auth_ip_acl = NULL;
-
+
#ifdef HAVE_CREDS
{
int a = 1;
if (!(p = protocol_new_internal(core, m, ma)))
return NULL;
-
+
p->server = server;
pa_socket_server_set_callback(p->server, on_connection, p);
l = pa_strlist_prepend(l, t);
pa_property_replace(core, PA_NATIVE_SERVER_PROPERTY_NAME, l);
}
-
+
return p;
}
if (p->server) {
char t[256];
-
+
if (pa_socket_server_get_address(p->server, t, sizeof(t))) {
pa_strlist *l;
l = pa_property_get(p->core, PA_NATIVE_SERVER_PROPERTY_NAME);
else
pa_property_remove(p->core, PA_NATIVE_SERVER_PROPERTY_NAME);
}
-
+
pa_socket_server_unref(p->server);
}
if (p->auth_ip_acl)
pa_ip_acl_free(p->auth_ip_acl);
-
+
#ifdef HAVE_CREDS
pa_xfree(p->auth_group);
#endif
return NULL;
on_connection(NULL, io, p);
-
+
return p;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_defer_event *defer_event;
int dead;
-
+
struct {
pa_memblock *current_memblock;
size_t memblock_index, fragment_size;
if (l > c->playback.fragment_size)
l = c->playback.fragment_size;
- if (c->playback.current_memblock)
+ if (c->playback.current_memblock)
if (c->playback.current_memblock->length - c->playback.memblock_index < l) {
pa_memblock_unref(c->playback.current_memblock);
c->playback.current_memblock = NULL;
assert(c->playback.current_memblock && c->playback.current_memblock->length >= l);
c->playback.memblock_index = 0;
}
-
+
if ((r = pa_iochannel_read(c->io, (uint8_t*) c->playback.current_memblock->data+c->playback.memblock_index, l)) <= 0) {
pa_log_debug("read(): %s", r == 0 ? "EOF" : pa_cstrerror(errno));
return -1;
assert(chunk.memblock);
c->playback.memblock_index += r;
-
+
assert(c->input_memblockq);
pa_memblockq_push_align(c->input_memblockq, &chunk);
assert(c->sink_input);
pa_sink_notify(c->sink_input->sink);
-
+
return 0;
}
ssize_t r;
if (!c->source_output)
- return 0;
+ return 0;
assert(c->output_memblockq);
if (pa_memblockq_peek(c->output_memblockq, &chunk) < 0)
return 0;
-
+
assert(chunk.memblock && chunk.length);
-
+
if ((r = pa_iochannel_write(c->io, (uint8_t*) chunk.memblock->data+chunk.index, chunk.length)) < 0) {
pa_memblock_unref(chunk.memblock);
pa_log("write(): %s", pa_cstrerror(errno));
return -1;
}
-
+
pa_memblockq_drop(c->output_memblockq, &chunk, r);
pa_memblock_unref(chunk.memblock);
pa_source_notify(c->source_output->source);
-
+
return 0;
}
if (c->dead)
return;
-
+
if (pa_iochannel_is_readable(c->io)) {
if (do_read(c) < 0)
goto fail;
if (pa_iochannel_is_writable(c->io)) {
if (do_write(c) < 0)
goto fail;
- }
+ }
return;
if (c->sink_input) {
c->dead = 1;
-
+
pa_iochannel_free(c->io);
c->io = NULL;
struct connection*c;
assert(i && i->userdata && chunk);
c = i->userdata;
-
+
if (pa_memblockq_peek(c->input_memblockq, chunk) < 0) {
-
+
if (c->dead)
connection_free(c);
-
+
return -1;
}
c->playback.memblock_index = 0;
c->playback.fragment_size = 0;
c->dead = 0;
-
+
pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname));
c->client = pa_client_new(p->core, __FILE__, cname);
assert(c->client);
pa_log("Failed to create sink input.");
goto fail;
}
-
+
c->sink_input->peek = sink_input_peek_cb;
c->sink_input->drop = sink_input_drop_cb;
c->sink_input->kill = sink_input_kill_cb;
c->defer_event = p->core->mainloop->defer_new(p->core->mainloop, defer_callback, c);
assert(c->defer_event);
p->core->mainloop->defer_enable(c->defer_event, 0);
-
+
return;
-
+
fail:
if (c)
connection_free(c);
p->source_name = pa_xstrdup(pa_modargs_get_value(ma, "source", NULL));
p->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));
-
+
enable = 0;
if (pa_modargs_get_value_boolean(ma, "record", &enable) < 0) {
pa_log("record= expects a numeric argument.");
pa_log("neither playback nor recording enabled for protocol.");
goto fail;
}
-
+
pa_socket_server_set_callback(p->server, on_connection, p);
-
+
return p;
fail:
if (p->connections) {
while((c = pa_idxset_first(p->connections, NULL)))
connection_free(c);
-
+
pa_idxset_free(p->connections, NULL, NULL);
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
struct pa_pstream {
PA_REFCNT_DECLARE;
-
+
pa_mainloop_api *mainloop;
pa_defer_event *defer_event;
pa_iochannel *io;
pa_pstream_ref(p);
pa_mutex_lock(p->mutex);
-
+
p->mainloop->defer_enable(p->defer_event, 0);
if (!p->dead && pa_iochannel_is_readable(p->io)) {
fail:
p->dead = 1;
-
+
if (p->die_callback)
p->die_callback(p, p->die_callback_userdata);
-
+
pa_mutex_unlock(p->mutex);
-
+
pa_pstream_unref(p);
}
static void io_callback(pa_iochannel*io, void *userdata) {
pa_pstream *p = userdata;
-
+
assert(p);
assert(p->io == io);
-
+
do_something(p);
}
assert(p);
assert(p->defer_event == e);
assert(p->mainloop == m);
-
+
do_something(p);
}
pa_pstream *pa_pstream_new(pa_mainloop_api *m, pa_iochannel *io, pa_mempool *pool) {
pa_pstream *p;
-
+
assert(m);
assert(io);
assert(pool);
p->mainloop = m;
p->defer_event = m->defer_new(m, defer_callback, p);
m->defer_enable(p->defer_event, 0);
-
+
p->send_queue = pa_queue_new();
assert(p->send_queue);
/* We do importing unconditionally */
p->import = pa_memimport_new(p->mempool, memimport_release_cb, p);
- pa_iochannel_socket_set_rcvbuf(io, 1024*8);
+ pa_iochannel_socket_set_rcvbuf(io, 1024*8);
pa_iochannel_socket_set_sndbuf(io, 1024*8);
#ifdef HAVE_CREDS
assert(p);
pa_pstream_close(p);
-
+
pa_queue_free(p->send_queue, item_free, NULL);
if (p->write.current)
if (p->read.memblock)
pa_memblock_unref(p->read.memblock);
-
+
if (p->read.packet)
pa_packet_unref(p->read.packet);
assert(packet);
pa_mutex_lock(p->mutex);
-
+
if (p->dead)
goto finish;
-
+
i = pa_xnew(struct item_info, 1);
i->type = PA_PSTREAM_ITEM_PACKET;
i->packet = pa_packet_ref(packet);
-
+
#ifdef HAVE_CREDS
if ((i->with_creds = !!creds))
i->creds = *creds;
void pa_pstream_send_memblock(pa_pstream*p, uint32_t channel, int64_t offset, pa_seek_mode_t seek_mode, const pa_memchunk *chunk) {
size_t length, idx;
-
+
assert(p);
assert(PA_REFCNT_VALUE(p) > 0);
assert(channel != (uint32_t) -1);
assert(chunk);
pa_mutex_lock(p->mutex);
-
+
if (p->dead)
goto finish;
while (length > 0) {
struct item_info *i;
size_t n;
-
+
i = pa_xnew(struct item_info, 1);
i->type = PA_PSTREAM_ITEM_MEMBLOCK;
i->chunk.index = chunk->index + idx;
i->chunk.length = n;
i->chunk.memblock = pa_memblock_ref(chunk->memblock);
-
+
i->channel = channel;
i->offset = offset;
i->seek_mode = seek_mode;
#ifdef HAVE_CREDS
i->with_creds = 0;
#endif
-
+
pa_queue_push(p->send_queue, i);
idx += n;
length -= n;
}
-
+
p->mainloop->defer_enable(p->defer_event, 1);
finish:
-
+
pa_mutex_unlock(p->mutex);
}
assert(PA_REFCNT_VALUE(p) > 0);
pa_mutex_lock(p->mutex);
-
+
if (p->dead)
goto finish;
assert(PA_REFCNT_VALUE(p) > 0);
pa_mutex_lock(p->mutex);
-
+
if (p->dead)
goto finish;
/* pa_log("Revoking block %u", block_id); */
-
+
item = pa_xnew(struct item_info, 1);
item->type = PA_PSTREAM_ITEM_SHMREVOKE;
item->block_id = block_id;
if (!(p->write.current = pa_queue_pop(p->send_queue)))
return;
-
+
p->write.index = 0;
p->write.data = NULL;
p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI] = 0;
p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO] = 0;
p->write.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS] = 0;
-
+
if (p->write.current->type == PA_PSTREAM_ITEM_PACKET) {
-
+
assert(p->write.current->packet);
p->write.data = p->write.current->packet->data;
p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->packet->length);
p->write.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS] = htonl(PA_FLAG_SHMREVOKE);
p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI] = htonl(p->write.current->block_id);
-
+
} else {
uint32_t flags;
int send_payload = 1;
-
+
assert(p->write.current->type == PA_PSTREAM_ITEM_MEMBLOCK);
assert(p->write.current->chunk.memblock);
-
+
p->write.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL] = htonl(p->write.current->channel);
p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI] = htonl((uint32_t) (((uint64_t) p->write.current->offset) >> 32));
p->write.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO] = htonl((uint32_t) ((uint64_t) p->write.current->offset));
&shm_id,
&offset,
&length) >= 0) {
-
+
flags |= PA_FLAG_SHMDATA;
send_payload = 0;
-
+
p->write.shm_info[PA_PSTREAM_SHM_BLOCKID] = htonl(block_id);
p->write.shm_info[PA_PSTREAM_SHM_SHMID] = htonl(shm_id);
p->write.shm_info[PA_PSTREAM_SHM_INDEX] = htonl((uint32_t) (offset + p->write.current->chunk.index));
p->write.shm_info[PA_PSTREAM_SHM_LENGTH] = htonl((uint32_t) p->write.current->chunk.length);
-
+
p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(sizeof(p->write.shm_info));
p->write.data = p->write.shm_info;
}
p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH] = htonl(p->write.current->chunk.length);
p->write.data = (uint8_t*) p->write.current->chunk.memblock->data + p->write.current->chunk.index;
}
-
+
p->write.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS] = htonl(flags);
}
void *d;
size_t l;
ssize_t r;
-
+
assert(p);
assert(PA_REFCNT_VALUE(p) > 0);
l = PA_PSTREAM_DESCRIPTOR_SIZE - p->write.index;
} else {
assert(p->write.data);
-
+
d = (uint8_t*) p->write.data + p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE;
l = ntohl(p->write.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) - (p->write.index - PA_PSTREAM_DESCRIPTOR_SIZE);
}
assert(l > 0);
-
+
#ifdef HAVE_CREDS
if (p->send_creds_now) {
static int do_read(pa_pstream *p) {
void *d;
- size_t l;
+ size_t l;
ssize_t r;
-
+
assert(p);
assert(PA_REFCNT_VALUE(p) > 0);
-
+
if (p->read.index < PA_PSTREAM_DESCRIPTOR_SIZE) {
d = (uint8_t*) p->read.descriptor + p->read.index;
l = PA_PSTREAM_DESCRIPTOR_SIZE - p->read.index;
#ifdef HAVE_CREDS
{
int b = 0;
-
+
if ((r = pa_iochannel_read_with_creds(p->io, d, l, &p->read_creds, &b)) <= 0)
return -1;
if ((r = pa_iochannel_read(p->io, d, l)) <= 0)
return -1;
#endif
-
+
p->read.index += r;
if (p->read.index == PA_PSTREAM_DESCRIPTOR_SIZE) {
pa_log_warn("Recieved SHM frame on a socket where SHM is disabled.");
return -1;
}
-
+
if (flags == PA_FLAG_SHMRELEASE) {
/* This is a SHM memblock release frame with no payload */
/* pa_log("Got release frame for %u", ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])); */
-
+
assert(p->export);
pa_memexport_process_release(p->export, ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI]));
goto frame_done;
-
+
} else if (flags == PA_FLAG_SHMREVOKE) {
/* This is a SHM memblock revoke frame with no payload */
}
length = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]);
-
+
if (length > FRAME_SIZE_MAX_ALLOW) {
pa_log_warn("Recieved invalid frame size : %lu", (unsigned long) length);
return -1;
}
-
+
assert(!p->read.packet && !p->read.memblock);
channel = ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL]);
-
+
if (channel == (uint32_t) -1) {
if (flags != 0) {
pa_log_warn("Received packet frame with invalid flags value.");
return -1;
}
-
+
/* Frame is a packet frame */
p->read.packet = pa_packet_new(length);
p->read.data = p->read.packet->data;
-
+
} else {
if ((flags & PA_FLAG_SEEKMASK) > PA_SEEK_RELATIVE_END) {
pa_log_warn("Received memblock frame with invalid seek mode.");
return -1;
}
-
+
if ((flags & PA_FLAG_SHMMASK) == PA_FLAG_SHMDATA) {
if (length != sizeof(p->read.shm_info)) {
pa_log_warn("Recieved SHM memblock frame with Invalid frame length.");
return -1;
}
-
+
/* Frame is a memblock frame referencing an SHM memblock */
p->read.data = p->read.shm_info;
} else if ((flags & PA_FLAG_SHMMASK) == 0) {
/* Frame is a memblock frame */
-
+
p->read.memblock = pa_memblock_new(p->mempool, length);
p->read.data = p->read.memblock->data;
} else {
-
+
pa_log_warn("Recieved memblock frame with invalid flags value.");
return -1;
}
}
-
+
} else if (p->read.index > PA_PSTREAM_DESCRIPTOR_SIZE) {
/* Frame payload available */
-
+
if (p->read.memblock && p->recieve_memblock_callback) {
/* Is this memblock data? Than pass it to the user */
l = (p->read.index - r) < PA_PSTREAM_DESCRIPTOR_SIZE ? p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE : (size_t) r;
-
+
if (l > 0) {
pa_memchunk chunk;
-
+
chunk.memblock = p->read.memblock;
chunk.index = p->read.index - PA_PSTREAM_DESCRIPTOR_SIZE - l;
chunk.length = l;
offset = (int64_t) (
(((uint64_t) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])) << 32) |
(((uint64_t) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO]))));
-
+
p->recieve_memblock_callback(
p,
ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL]),
/* Frame complete */
if (p->read.index >= ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_LENGTH]) + PA_PSTREAM_DESCRIPTOR_SIZE) {
-
+
if (p->read.memblock) {
/* This was a memblock frame. We can unref the memblock now */
pa_memblock_unref(p->read.memblock);
} else if (p->read.packet) {
-
+
if (p->recieve_packet_callback)
#ifdef HAVE_CREDS
p->recieve_packet_callback(p, p->read.packet, p->read_creds_valid ? &p->read_creds : NULL, p->recieve_packet_callback_userdata);
pa_packet_unref(p->read.packet);
} else {
pa_memblock *b;
-
+
assert((ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_FLAGS]) & PA_FLAG_SHMMASK) == PA_FLAG_SHMDATA);
assert(p->import);
if (p->recieve_memblock_callback) {
int64_t offset;
pa_memchunk chunk;
-
+
chunk.memblock = b;
chunk.index = 0;
chunk.length = b->length;
offset = (int64_t) (
(((uint64_t) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_HI])) << 32) |
(((uint64_t) ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_OFFSET_LO]))));
-
+
p->recieve_memblock_callback(
p,
ntohl(p->read.descriptor[PA_PSTREAM_DESCRIPTOR_CHANNEL]),
void pa_pstream_set_die_callback(pa_pstream *p, pa_pstream_notify_cb_t cb, void *userdata) {
assert(p);
assert(PA_REFCNT_VALUE(p) > 0);
-
+
pa_mutex_lock(p->mutex);
p->die_callback = cb;
p->die_callback_userdata = userdata;
pa_pstream* pa_pstream_ref(pa_pstream*p) {
assert(p);
assert(PA_REFCNT_VALUE(p) > 0);
-
+
PA_REFCNT_INC(p);
return p;
}
assert(p);
pa_mutex_lock(p->mutex);
-
+
p->dead = 1;
if (p->import) {
p->use_shm = enable;
if (enable) {
-
+
if (!p->export)
p->export = pa_memexport_new(p->mempool, memexport_revoke_cb, p);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_xfree(e);
q->length--;
-
+
return p;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
void pa_random_seed(void);
void pa_random(void *ret_data, size_t length);
-
+
#endif
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_memblock *buf1_block, *buf2_block, *buf3_block, *buf4_block;
float* buf1, *buf2, *buf3, *buf4;
unsigned buf1_samples, buf2_samples, buf3_samples, buf4_samples;
-
+
pa_convert_to_float32ne_func_t to_float32ne_func;
pa_convert_from_float32ne_func_t from_float32ne_func;
SRC_STATE *src_state;
const pa_sample_spec *b,
const pa_channel_map *bm,
pa_resample_method_t resample_method) {
-
+
pa_resampler *r = NULL;
assert(pool);
r->o_cm = *bm;
else
pa_channel_map_init_auto(&r->o_cm, r->o_ss.channels, PA_CHANNEL_MAP_DEFAULT);
-
+
r->i_fz = pa_frame_size(a);
r->o_fz = pa_frame_size(b);
if (libsamplerate_init(r) < 0)
goto fail;
-
+
} else {
/* Use our own simple non-fp resampler for the trivial cases and when the user selects it */
if (trivial_init(r) < 0)
goto fail;
}
-
+
return r;
-
+
fail:
if (r)
pa_xfree(r);
-
+
return NULL;
}
if (r->impl_free)
r->impl_free(r);
-
+
pa_xfree(r);
}
if (r->i_ss.rate == rate)
return;
-
+
r->i_ss.rate = rate;
-
+
if (r->impl_update_input_rate)
r->impl_update_input_rate(r, rate);
}
size_t pa_resampler_request(pa_resampler *r, size_t out_length) {
assert(r);
-
+
return (((out_length / r->o_fz)*r->i_ss.rate)/r->o_ss.rate) * r->i_fz;
}
pa_resample_method_t pa_parse_resample_method(const char *string) {
pa_resample_method_t m;
-
+
assert(string);
for (m = 0; m < PA_RESAMPLER_MAX; m++)
assert(r);
assert(r->impl_data);
-
+
u = r->impl_data;
-
+
if (u->src_state)
src_delete(u->src_state);
for (ic = 0; ic < r->i_ss.channels; ic++) {
pa_channel_position_t a, b;
-
+
a = r->i_cm.map[ic];
b = r->o_cm.map[oc];
-
+
if (a == b ||
(a == PA_CHANNEL_POSITION_MONO && b == PA_CHANNEL_POSITION_LEFT) ||
(a == PA_CHANNEL_POSITION_MONO && b == PA_CHANNEL_POSITION_RIGHT) ||
(a == PA_CHANNEL_POSITION_LEFT && b == PA_CHANNEL_POSITION_MONO) ||
(a == PA_CHANNEL_POSITION_RIGHT && b == PA_CHANNEL_POSITION_MONO))
-
+
u->map_table[oc][i++] = ic;
}
assert(input);
assert(r->impl_data);
u = r->impl_data;
-
+
/* Convert the incoming sample into floats and place them in buf1 */
if (!u->to_float32ne_func)
return input;
-
+
n_samples = n_frames * r->i_ss.channels;
if (u->buf1_samples < n_samples) {
u->buf1_block = pa_memblock_new(r->mempool, sizeof(float) * n_samples);
u->buf1 = u->buf1_block->data;
}
-
+
u->to_float32ne_func(n_samples, input, u->buf1);
return u->buf1;
unsigned n_samples;
int i_skip, o_skip;
unsigned oc;
-
+
assert(r);
assert(input);
assert(r->impl_data);
u = r->impl_data;
/* Remap channels and place the result int buf2 */
-
+
if (!u->map_required)
return input;
o_skip = sizeof(float) * r->o_ss.channels;
i_skip = sizeof(float) * r->i_ss.channels;
-
+
for (oc = 0; oc < r->o_ss.channels; oc++) {
unsigned i;
static const float one = 1.0;
u = r->impl_data;
/* Resample the data and place the result in buf3 */
-
+
if (!u->src_state)
return input;
u->buf3_block = pa_memblock_new(r->mempool, sizeof(float) * out_n_samples);
u->buf3 = u->buf3_block->data;
}
-
+
data.data_in = input;
data.input_frames = *n_frames;
data.data_out = u->buf3;
data.output_frames = out_n_frames;
-
+
data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate;
data.end_of_input = 0;
-
+
ret = src_process(u->src_state, &data);
assert(ret == 0);
assert((unsigned) data.input_frames_used == *n_frames);
static void *convert_from_float(pa_resampler *r, float *input, unsigned n_frames) {
struct impl_libsamplerate *u;
unsigned n_samples;
-
+
assert(r);
assert(input);
assert(r->impl_data);
u = r->impl_data;
-
+
/* Convert the data into the correct sample type and place the result in buf4 */
if (!u->from_float32ne_func)
return input;
-
+
n_samples = n_frames * r->o_ss.channels;
if (u->buf4_samples < n_samples) {
u->buf4_block = pa_memblock_new(r->mempool, sizeof(float) * n_samples);
u->buf4 = u->buf4_block->data;
}
-
+
u->from_float32ne_func(n_samples, input, u->buf4);
return u->buf4;
assert(in->memblock);
assert(in->length % r->i_fz == 0);
assert(r->impl_data);
-
+
u = r->impl_data;
input = ((uint8_t*) in->memblock->data + in->index);
n_frames = in->length / r->i_fz;
assert(n_frames > 0);
-
+
buf = convert_to_float(r, input, n_frames);
buf = remap_channels(r, buf, n_frames);
buf = resample(r, buf, &n_frames);
out->length = n_frames * r->o_fz;
out->index = 0;
out->memblock = NULL;
-
+
if (output == u->buf1) {
u->buf1 = NULL;
u->buf1_samples = 0;
static void libsamplerate_update_input_rate(pa_resampler *r, uint32_t rate) {
struct impl_libsamplerate *u;
-
+
assert(r);
assert(rate > 0);
assert(r->impl_data);
r->impl_run = libsamplerate_run;
calc_map_table(r);
-
+
return 0;
fail:
assert(in);
assert(out);
assert(r->impl_data);
-
+
u = r->impl_data;
fz = r->i_fz;
/* Do real resampling */
size_t l;
unsigned o_index;
-
+
/* The length of the new memory block rounded up */
l = ((((n_frames+1) * r->o_ss.rate) / r->i_ss.rate) + 1) * fz;
-
+
out->index = 0;
out->memblock = pa_memblock_new(r->mempool, l);
-
+
for (o_index = 0;; o_index++, u->o_counter++) {
unsigned j;
-
+
j = (u->o_counter * r->i_ss.rate / r->o_ss.rate);
j = j > u->i_counter ? j - u->i_counter : 0;
-
+
if (j >= n_frames)
break;
assert(o_index*fz < out->memblock->length);
-
+
memcpy((uint8_t*) out->memblock->data + fz*o_index,
(uint8_t*) in->memblock->data + in->index + fz*j, fz);
-
+
}
-
+
out->length = o_index*fz;
}
u->i_counter += n_frames;
-
+
/* Normalize counters */
while (u->i_counter >= r->i_ss.rate) {
u->i_counter -= r->i_ss.rate;
static void trivial_free(pa_resampler *r) {
assert(r);
-
+
pa_xfree(r->impl_data);
}
static int trivial_init(pa_resampler*r) {
struct impl_trivial *u;
-
+
assert(r);
assert(r->i_ss.format == r->o_ss.format);
assert(r->i_ss.channels == r->o_ss.channels);
r->impl_run = trivial_run;
r->impl_free = trivial_free;
r->impl_update_input_rate = trivial_update_input_rate;
-
+
return 0;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
default:
assert(0);
}
-
+
memset(p, c, length);
}
const pa_sample_spec *spec,
const pa_cvolume *volume,
int mute) {
-
+
assert(streams && data && length && spec);
switch (spec->format) {
case PA_SAMPLE_S16NE:{
size_t d;
unsigned channel = 0;
-
+
for (d = 0;; d += sizeof(int16_t)) {
int32_t sum = 0;
-
+
if (d >= length)
return d;
if (!mute && volume->values[channel] != PA_VOLUME_MUTED) {
unsigned i;
-
+
for (i = 0; i < nstreams; i++) {
int32_t v;
pa_volume_t cvolume = streams[i].volume.values[channel];
-
+
if (d >= streams[i].chunk.length)
return d;
-
+
if (cvolume == PA_VOLUME_MUTED)
v = 0;
else {
v = *((int16_t*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d));
-
+
if (cvolume != PA_VOLUME_NORM)
v = (int32_t) (v * pa_sw_volume_to_linear(cvolume));
}
-
+
sum += v;
}
-
+
if (volume->values[channel] != PA_VOLUME_NORM)
sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel]));
if (sum > 0x7FFF) sum = 0x7FFF;
}
-
+
*((int16_t*) data) = sum;
data = (uint8_t*) data + sizeof(int16_t);
-
+
if (++channel >= spec->channels)
channel = 0;
}
case PA_SAMPLE_S16RE:{
size_t d;
unsigned channel = 0;
-
+
for (d = 0;; d += sizeof(int16_t)) {
int32_t sum = 0;
-
+
if (d >= length)
return d;
if (!mute && volume->values[channel] != PA_VOLUME_MUTED) {
unsigned i;
-
+
for (i = 0; i < nstreams; i++) {
int32_t v;
pa_volume_t cvolume = streams[i].volume.values[channel];
-
+
if (d >= streams[i].chunk.length)
return d;
-
+
if (cvolume == PA_VOLUME_MUTED)
v = 0;
else {
v = INT16_SWAP(*((int16_t*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d)));
-
+
if (cvolume != PA_VOLUME_NORM)
v = (int32_t) (v * pa_sw_volume_to_linear(cvolume));
}
-
+
sum += v;
}
-
+
if (volume->values[channel] != PA_VOLUME_NORM)
sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel]));
if (sum > 0x7FFF) sum = 0x7FFF;
}
-
+
*((int16_t*) data) = INT16_SWAP(sum);
data = (uint8_t*) data + sizeof(int16_t);
-
+
if (++channel >= spec->channels)
channel = 0;
}
}
-
+
case PA_SAMPLE_U8: {
size_t d;
unsigned channel = 0;
-
+
for (d = 0;; d ++) {
int32_t sum = 0;
-
+
if (d >= length)
return d;
if (!mute && volume->values[channel] != PA_VOLUME_MUTED) {
unsigned i;
-
+
for (i = 0; i < nstreams; i++) {
int32_t v;
pa_volume_t cvolume = streams[i].volume.values[channel];
-
+
if (d >= streams[i].chunk.length)
return d;
-
+
if (cvolume == PA_VOLUME_MUTED)
v = 0;
else {
v = (int32_t) *((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d) - 0x80;
-
+
if (cvolume != PA_VOLUME_NORM)
v = (int32_t) (v * pa_sw_volume_to_linear(cvolume));
}
if (sum > 0x7F) sum = 0x7F;
}
-
+
*((uint8_t*) data) = (uint8_t) (sum + 0x80);
data = (uint8_t*) data + 1;
-
+
if (++channel >= spec->channels)
channel = 0;
}
}
-
+
case PA_SAMPLE_FLOAT32NE: {
size_t d;
unsigned channel = 0;
-
+
for (d = 0;; d += sizeof(float)) {
float sum = 0;
-
+
if (d >= length)
return d;
-
+
if (!mute && volume->values[channel] != PA_VOLUME_MUTED) {
unsigned i;
-
+
for (i = 0; i < nstreams; i++) {
float v;
pa_volume_t cvolume = streams[i].volume.values[channel];
-
+
if (d >= streams[i].chunk.length)
return d;
-
+
if (cvolume == PA_VOLUME_MUTED)
v = 0;
else {
v = *((float*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d));
-
+
if (cvolume != PA_VOLUME_NORM)
v *= pa_sw_volume_to_linear(cvolume);
}
-
+
sum += v;
}
-
+
if (volume->values[channel] != PA_VOLUME_NORM)
sum *= pa_sw_volume_to_linear(volume->values[channel]);
}
-
+
*((float*) data) = sum;
data = (uint8_t*) data + sizeof(float);
channel = 0;
}
}
-
+
default:
pa_log_error("ERROR: Unable to mix audio data of format %s.", pa_sample_format_to_string(spec->format));
abort();
for (channel = 0; channel < spec->channels; channel++)
linear[channel] = pa_sw_volume_to_linear(volume->values[channel]);
-
+
for (channel = 0, d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) {
int32_t t = (int32_t)(*d);
-
+
t = (int32_t) (t * linear[channel]);
-
+
if (t < -0x8000) t = -0x8000;
if (t > 0x7FFF) t = 0x7FFF;
-
+
*d = (int16_t) t;
-
+
if (++channel >= spec->channels)
channel = 0;
}
size_t n;
unsigned channel;
double linear[PA_CHANNELS_MAX];
-
+
for (channel = 0; channel < spec->channels; channel++)
linear[channel] = pa_sw_volume_to_linear(volume->values[channel]);
-
+
for (channel = 0, d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) {
int32_t t = (int32_t)(INT16_SWAP(*d));
-
+
t = (int32_t) (t * linear[channel]);
-
+
if (t < -0x8000) t = -0x8000;
if (t > 0x7FFF) t = 0x7FFF;
-
+
*d = INT16_SWAP((int16_t) t);
-
+
if (++channel >= spec->channels)
channel = 0;
}
break;
}
-
+
case PA_SAMPLE_U8: {
uint8_t *d;
size_t n;
unsigned channel = 0;
-
+
for (d = (uint8_t*) c->memblock->data + c->index, n = c->length; n > 0; d++, n--) {
int32_t t = (int32_t) *d - 0x80;
-
+
t = (int32_t) (t * pa_sw_volume_to_linear(volume->values[channel]));
-
+
if (t < -0x80) t = -0x80;
if (t > 0x7F) t = 0x7F;
-
+
*d = (uint8_t) (t + 0x80);
-
+
if (++channel >= spec->channels)
channel = 0;
}
break;
}
-
+
case PA_SAMPLE_FLOAT32NE: {
float *d;
int skip;
unsigned n;
unsigned channel;
-
+
d = (float*) ((uint8_t*) c->memblock->data + c->index);
skip = spec->channels * sizeof(float);
n = c->length/sizeof(float)/spec->channels;
-
+
for (channel = 0; channel < spec->channels ; channel ++) {
float v, *t;
-
+
if (volume->values[channel] == PA_VOLUME_NORM)
continue;
-
+
v = (float) pa_sw_volume_to_linear(volume->values[channel]);
-
+
t = d + channel;
oil_scalarmult_f32(t, skip, t, skip, &v, n);
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
assert(b);
#if SWAP_WORDS == 1
-
+
for (; n > 0; n--) {
int16_t s = *(ca++);
*(b++) = ((float) INT16_FROM(s))/0x7FFF;
void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b) {
int16_t *cb = b;
-
+
assert(a);
assert(b);
#if SWAP_WORDS == 1
-
+
for (; n > 0; n--) {
int16_t s;
float v = *(a++);
if (v > 1)
v = 1;
-
+
if (v < -1)
v = -1;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
static void u8_to_float32ne(unsigned n, const void *a, float *b) {
const uint8_t *ca = a;
static const double add = -128.0/127.0, factor = 1.0/127.0;
-
+
assert(a);
assert(b);
oil_scaleconv_f32_u8(b, ca, n, &add, &factor);
-}
+}
static void u8_from_float32ne(unsigned n, const float *a, void *b) {
uint8_t *cb = b;
assert(a);
assert(b);
-
+
for (; n > 0; n--)
*(b++) = st_ulaw2linear16(*(ca++)) * 1.0F / 0x7FFF;
}
assert(a);
assert(b);
-
+
for (; n > 0; n--) {
float v = *(a++);
assert(a);
assert(b);
-
+
for (; n > 0; n--) {
float v = *(a++);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
#if defined(__linux__) && !defined(MADV_REMOVE)
#define MADV_REMOVE 9
-#endif
+#endif
#define MAX_SHM_SIZE (1024*1024*20)
int pa_shm_create_rw(pa_shm *m, size_t size, int shared, mode_t mode) {
char fn[32];
int fd = -1;
-
+
assert(m);
assert(size > 0);
assert(size < MAX_SHM_SIZE);
#elif defined(HAVE_POSIX_MEMALIGN)
{
int r;
-
+
if ((r = posix_memalign(&m->ptr, sysconf(_SC_PAGESIZE), size)) < 0) {
pa_log("posix_memalign() failed: %s", pa_cstrerror(r));
goto fail;
#else
m->ptr = pa_xmalloc(m->size);
#endif
-
+
m->do_unlink = 0;
-
+
} else {
#ifdef HAVE_SHM_OPEN
pa_random(&m->id, sizeof(m->id));
pa_log("shm_open() failed: %s", pa_cstrerror(errno));
goto fail;
}
-
+
if (ftruncate(fd, m->size = size) < 0) {
pa_log("ftruncate() failed: %s", pa_cstrerror(errno));
goto fail;
}
-
+
if ((m->ptr = mmap(NULL, m->size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) {
pa_log("mmap() failed: %s", pa_cstrerror(errno));
goto fail;
}
m->shared = shared;
-
+
return 0;
-
+
fail:
#ifdef HAVE_SHM_OPEN
char fn[32];
segment_name(fn, sizeof(fn), m->id);
-
+
if (shm_unlink(fn) < 0)
pa_log(" shm_unlink(%s) failed: %s", fn, pa_cstrerror(errno));
}
void pa_shm_punch(pa_shm *m, size_t offset, size_t size) {
void *ptr;
-
+
assert(m);
assert(m->ptr);
assert(m->size > 0);
* support it */
ptr = (uint8_t*) m->ptr + offset;
-
+
#ifdef __linux__
{
/* On Linux ptr must be page aligned */
unsigned o;
o = ((unsigned long) ptr) - ((((unsigned long) ptr)/psz) * psz);
-
+
if (o > 0) {
ptr = (uint8_t*) ptr + (psz - o);
size -= psz - o;
}
}
#endif
-
+
#ifdef MADV_REMOVE
if (madvise(ptr, size, MADV_REMOVE) >= 0)
return;
#ifdef MADV_FREE
if (madvise(ptr, size, MADV_FREE) >= 0)
return;
-#endif
-
+#endif
+
#ifdef MADV_DONTNEED
madvise(ptr, size, MADV_DONTNEED);
#endif
}
m->size = st.st_size;
-
+
if ((m->ptr = mmap(NULL, m->size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
pa_log("mmap() failed: %s", pa_cstrerror(errno));
goto fail;
m->do_unlink = 0;
m->shared = 1;
-
+
close(fd);
-
+
return 0;
-
+
fail:
if (fd >= 0)
close(fd);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data) {
assert(data);
-
+
memset(data, 0, sizeof(*data));
data->resample_method = PA_RESAMPLER_INVALID;
return data;
pa_core *core,
pa_sink_input_new_data *data,
pa_sink_input_flags_t flags) {
-
+
pa_sink_input *i;
pa_resampler *resampler = NULL;
int r;
if (!data->sink)
data->sink = pa_namereg_get(core, NULL, PA_NAMEREG_SINK, 1);
-
+
CHECK_VALIDITY_RETURN_NULL(data->sink);
CHECK_VALIDITY_RETURN_NULL(data->sink->state == PA_SINK_RUNNING);
if (!data->sample_spec_is_set)
data->sample_spec = data->sink->sample_spec;
-
+
CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(&data->sample_spec));
-
+
if (!data->channel_map_is_set)
pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
-
+
CHECK_VALIDITY_RETURN_NULL(pa_channel_map_valid(&data->channel_map));
CHECK_VALIDITY_RETURN_NULL(data->channel_map.channels == data->sample_spec.channels);
-
+
if (!data->volume_is_set)
pa_cvolume_reset(&data->volume, data->sample_spec.channels);
if ((flags & PA_SINK_INPUT_VARIABLE_RATE) ||
!pa_sample_spec_equal(&data->sample_spec, &data->sink->sample_spec) ||
!pa_channel_map_equal(&data->channel_map, &data->sink->channel_map))
-
+
if (!(resampler = pa_resampler_new(
- core->mempool,
+ core->mempool,
&data->sample_spec, &data->channel_map,
&data->sink->sample_spec, &data->sink->channel_map,
data->resample_method))) {
i->sample_spec = data->sample_spec;
i->channel_map = data->channel_map;
i->volume = data->volume;
-
+
i->peek = NULL;
i->drop = NULL;
i->kill = NULL;
i->get_latency = NULL;
i->underrun = NULL;
i->userdata = NULL;
-
+
i->move_silence = 0;
pa_memchunk_reset(&i->resampled_chunk);
i->resampler = resampler;
i->resample_method = data->resample_method;
i->silence_memblock = NULL;
-
+
r = pa_idxset_put(core->sink_inputs, i, &i->index);
assert(r == 0);
r = pa_idxset_put(i->sink->inputs, i, NULL);
i->name,
i->sink->name,
pa_sample_spec_snprint(st, sizeof(st), &i->sample_spec));
-
+
pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_NEW, i->index);
/* We do not call pa_sink_notify() here, because the virtual
* functions have not yet been initialized */
-
- return i;
+
+ return i;
}
void pa_sink_input_disconnect(pa_sink_input *i) {
if (i->state != PA_SINK_INPUT_DISCONNECTED)
pa_sink_input_disconnect(i);
- pa_log_info("freed %u \"%s\"", i->index, i->name);
-
+ pa_log_info("freed %u \"%s\"", i->index, i->name);
+
if (i->resampled_chunk.memblock)
pa_memblock_unref(i->resampled_chunk.memblock);
-
+
if (i->resampler)
pa_resampler_free(i->resampler);
if (i->silence_memblock)
pa_memblock_unref(i->silence_memblock);
-
+
pa_xfree(i->name);
pa_xfree(i->driver);
pa_xfree(i);
pa_sink_input* pa_sink_input_ref(pa_sink_input *i) {
assert(i);
assert(i->ref >= 1);
-
+
i->ref++;
return i;
}
pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) {
pa_usec_t r = 0;
-
+
assert(i);
assert(i->ref >= 1);
-
+
if (i->get_latency)
r += i->get_latency(i);
int ret = -1;
int do_volume_adj_here;
int volume_is_norm;
-
+
assert(i);
assert(i->ref >= 1);
assert(chunk);
/* We have just been moved and shall play some silence for a
* while until the old sink has drained its playback buffer */
-
+
if (!i->silence_memblock)
i->silence_memblock = pa_silence_memblock_new(i->sink->core->mempool, &i->sink->sample_spec, SILENCE_BUFFER_LENGTH);
do_volume_adj_here = 1;
goto finish;
}
-
+
if (!i->resampler) {
do_volume_adj_here = 0;
ret = i->peek(i, chunk);
do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map);
volume_is_norm = pa_cvolume_is_norm(&i->volume);
-
+
while (!i->resampled_chunk.memblock) {
pa_memchunk tchunk;
size_t l;
-
+
if ((ret = i->peek(i, &tchunk)) < 0)
goto finish;
assert(tchunk.length);
-
+
l = pa_resampler_request(i->resampler, CONVERT_BUFFER_LENGTH);
if (l > tchunk.length)
assert(i->resampled_chunk.memblock);
assert(i->resampled_chunk.length);
-
+
*chunk = i->resampled_chunk;
pa_memblock_ref(i->resampled_chunk.memblock);
/* We've both the same channel map, so let's have the sink do the adjustment for us*/
*volume = i->volume;
}
-
+
pa_sink_input_unref(i);
-
+
return ret;
}
if (chunk->memblock != i->silence_memblock ||
chunk->index != 0 ||
- (chunk->memblock && (chunk->length != (i->silence_memblock->length < i->move_silence ? i->silence_memblock->length : i->move_silence))))
+ (chunk->memblock && (chunk->length != (i->silence_memblock->length < i->move_silence ? i->silence_memblock->length : i->move_silence))))
return;
-
+
}
assert(i->move_silence >= length);
-
+
i->move_silence -= length;
if (i->move_silence <= 0) {
i->drop(i, chunk, length);
return;
}
-
+
assert(i->resampled_chunk.memblock);
assert(i->resampled_chunk.length >= length);
if (pa_cvolume_equal(&i->volume, volume))
return;
-
+
i->volume = *volume;
pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
}
void pa_sink_input_cork(pa_sink_input *i, int b) {
int n;
-
+
assert(i);
assert(i->ref >= 1);
if (i->name && name && !strcmp(i->name, name))
return;
-
+
pa_xfree(i->name);
i->name = pa_xstrdup(name);
pa_resampler *new_resampler = NULL;
pa_memblockq *buffer = NULL;
pa_sink *origin;
-
+
assert(i);
assert(dest);
/* Try to reuse the old resampler if possible */
new_resampler = i->resampler;
-
+
else if ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ||
!pa_sample_spec_equal(&i->sample_spec, &dest->sample_spec) ||
!pa_channel_map_equal(&i->channel_map, &dest->channel_map)) {
/* Okey, we need a new resampler for the new sink */
-
+
if (!(new_resampler = pa_resampler_new(
dest->core->mempool,
&i->sample_spec, &i->channel_map,
pa_usec_t silence_usec = 0;
buffer = pa_memblockq_new(0, MOVE_BUFFER_LENGTH, 0, pa_frame_size(&origin->sample_spec), 0, 0, NULL);
-
+
/* Let's do a little bit of Voodoo for compensating latency
* differences */
old_latency = pa_sink_get_latency(origin);
new_latency = pa_sink_get_latency(dest);
-
+
/* The already resampled data should go to the old sink */
if (old_latency >= new_latency) {
* while */
silence_usec = old_latency - new_latency;
-
+
} else {
size_t l;
int volume_is_norm;
-
+
/* The latency of new sink is larger than the latency of
* the old sink. Therefore we have to precompute a little
* and make sure that this is still played on the old
* sink, until we can play the first sample on the new
* sink.*/
-
+
l = pa_usec_to_bytes(new_latency - old_latency, &origin->sample_spec);
volume_is_norm = pa_cvolume_is_norm(&i->volume);
i->resampled_chunk.memblock = NULL;
i->resampled_chunk.index = i->resampled_chunk.length = 0;
}
-
+
/* Notify everyone */
pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
pa_sink_notify(i->sink);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
uint32_t index;
pa_sink_input_state_t state;
pa_sink_input_flags_t flags;
-
+
char *name, *driver; /* may be NULL */
- pa_module *module; /* may be NULL */
- pa_client *client; /* may be NULL */
+ pa_module *module; /* may be NULL */
+ pa_client *client; /* may be NULL */
pa_sink *sink;
-
+
pa_sample_spec sample_spec;
pa_channel_map channel_map;
pa_cvolume volume;
* compensate for latency differences when moving a sink input
* "hot" between sinks. */
size_t move_silence;
-
+
int (*peek) (pa_sink_input *i, pa_memchunk *chunk);
void (*drop) (pa_sink_input *i, const pa_memchunk *chunk, size_t length);
void (*kill) (pa_sink_input *i); /* may be NULL */
const char *name, *driver;
pa_module *module;
pa_client *client;
-
+
pa_sink *sink;
-
+
pa_sample_spec sample_spec;
int sample_spec_is_set;
pa_channel_map channel_map;
int channel_map_is_set;
pa_cvolume volume;
int volume_is_set;
-
+
pa_resample_method_t resample_method;
} pa_sink_input_new_data;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
int fail,
const pa_sample_spec *spec,
const pa_channel_map *map) {
-
+
pa_sink *s;
char *n = NULL;
char st[256];
assert(spec);
CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(spec));
-
+
if (!map)
map = pa_channel_map_init_auto(&tmap, spec->channels, PA_CHANNEL_MAP_DEFAULT);
CHECK_VALIDITY_RETURN_NULL(map->channels == spec->channels);
CHECK_VALIDITY_RETURN_NULL(!driver || pa_utf8_valid(driver));
CHECK_VALIDITY_RETURN_NULL(pa_utf8_valid(name) && *name);
-
+
s = pa_xnew(pa_sink, 1);
if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SINK, s, fail))) {
s->sample_spec = *spec;
s->channel_map = *map;
-
+
s->inputs = pa_idxset_new(NULL, NULL);
pa_cvolume_reset(&s->sw_volume, spec->channels);
s->hw_muted = 0;
s->is_hardware = 0;
-
+
s->get_latency = NULL;
s->notify = NULL;
s->set_hw_volume = NULL;
r = pa_idxset_put(core->sinks, s, &s->index);
assert(s->index != PA_IDXSET_INVALID && r >= 0);
-
+
pa_sample_spec_snprint(st, sizeof(st), spec);
pa_log_info("created %u \"%s\" with sample spec \"%s\"", s->index, s->name, st);
n = pa_sprintf_malloc("%s.monitor", name);
-
+
if (!(s->monitor_source = pa_source_new(core, driver, n, 0, spec, map)))
pa_log_warn("failed to create monitor source.");
else {
}
pa_xfree(n);
-
+
pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index);
-
+
return s;
}
void pa_sink_disconnect(pa_sink* s) {
pa_sink_input *i, *j = NULL;
-
+
assert(s);
assert(s->state == PA_SINK_RUNNING);
pa_namereg_unregister(s->core, s->name);
pa_hook_fire(&s->core->hook_sink_disconnect, s);
-
+
while ((i = pa_idxset_first(s->inputs, NULL))) {
assert(i != j);
pa_sink_input_kill(i);
s->set_hw_volume = NULL;
s->set_hw_mute = NULL;
s->get_hw_mute = NULL;
-
+
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
}
static void sink_free(pa_sink *s) {
assert(s);
assert(!s->ref);
-
+
if (s->state != PA_SINK_DISCONNECTED)
pa_sink_disconnect(s);
- pa_log_info("freed %u \"%s\"", s->index, s->name);
+ pa_log_info("freed %u \"%s\"", s->index, s->name);
if (s->monitor_source) {
pa_source_unref(s->monitor_source);
s->monitor_source = NULL;
}
-
+
pa_idxset_free(s->inputs, NULL, NULL);
pa_xfree(s->name);
pa_sink* pa_sink_ref(pa_sink *s) {
assert(s);
assert(s->ref >= 1);
-
+
s->ref++;
return s;
}
uint32_t idx = PA_IDXSET_INVALID;
pa_sink_input *i;
unsigned n = 0;
-
+
assert(s);
assert(s->ref >= 1);
assert(info);
}
info->userdata = i;
-
+
assert(info->chunk.memblock);
assert(info->chunk.memblock->data);
assert(info->chunk.length);
-
+
info++;
maxinfo--;
n++;
for (; maxinfo > 0; maxinfo--, info++) {
pa_sink_input *i = info->userdata;
-
+
assert(i);
assert(info->chunk.memblock);
info->userdata = NULL;
}
}
-
+
int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
pa_mix_info info[MAX_MIX_CHANNELS];
unsigned n;
int r = -1;
-
+
assert(s);
assert(s->ref >= 1);
assert(length);
assert(result);
pa_sink_ref(s);
-
+
n = fill_mix_info(s, info, MAX_MIX_CHANNELS);
if (n <= 0)
result->length = length;
pa_sw_cvolume_multiply(&volume, &s->sw_volume, &info[0].volume);
-
+
if (s->sw_muted || !pa_cvolume_is_norm(&volume)) {
pa_memchunk_make_writable(result, 0);
if (s->sw_muted)
pa_mix_info info[MAX_MIX_CHANNELS];
unsigned n;
int r = -1;
-
+
assert(s);
assert(s->ref >= 1);
assert(target);
assert(target->memblock->data);
pa_sink_ref(s);
-
+
n = fill_mix_info(s, info, MAX_MIX_CHANNELS);
if (n <= 0)
if (target->length > info[0].chunk.length)
target->length = info[0].chunk.length;
-
+
memcpy((uint8_t*) target->memblock->data + target->index,
(uint8_t*) info[0].chunk.memblock->data + info[0].chunk.index,
target->length);
pa_sw_cvolume_multiply(&volume, &s->sw_volume, &info[0].volume);
if (s->sw_muted)
- pa_silence_memchunk(target, &s->sample_spec);
+ pa_silence_memchunk(target, &s->sample_spec);
else if (!pa_cvolume_is_norm(&volume))
pa_volume_memchunk(target, &s->sample_spec, &volume);
} else
&s->sample_spec,
&s->sw_volume,
s->sw_muted);
-
+
inputs_drop(s, info, n, target->length);
if (s->monitor_source)
finish:
pa_sink_unref(s);
-
+
return r;
}
void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
pa_memchunk chunk;
size_t l, d;
-
+
assert(s);
assert(s->ref >= 1);
assert(target);
assert(target->memblock->data);
pa_sink_ref(s);
-
+
l = target->length;
d = 0;
while (l > 0) {
chunk = *target;
chunk.index += d;
chunk.length -= d;
-
+
if (pa_sink_render_into(s, &chunk) < 0)
break;
assert(result);
/*** This needs optimization ***/
-
+
result->memblock = pa_memblock_new(s->core->mempool, result->length = length);
result->index = 0;
if (s->owner == m)
return;
-
+
s->owner = m;
if (s->monitor_source)
void pa_sink_set_volume(pa_sink *s, pa_mixer_t m, const pa_cvolume *volume) {
pa_cvolume *v;
-
+
assert(s);
assert(s->ref >= 1);
assert(volume);
- if (m == PA_MIXER_HARDWARE && s->set_hw_volume)
+ if (m == PA_MIXER_HARDWARE && s->set_hw_volume)
v = &s->hw_volume;
else
v = &s->sw_volume;
if (pa_cvolume_equal(v, volume))
return;
-
+
*v = *volume;
if (v == &s->hw_volume)
if (s->get_hw_volume)
s->get_hw_volume(s);
-
+
return &s->hw_volume;
} else
return &s->sw_volume;
void pa_sink_set_mute(pa_sink *s, pa_mixer_t m, int mute) {
int *t;
-
+
assert(s);
assert(s->ref >= 1);
- if (m == PA_MIXER_HARDWARE && s->set_hw_mute)
+ if (m == PA_MIXER_HARDWARE && s->set_hw_mute)
t = &s->hw_muted;
else
t = &s->sw_muted;
if (!!*t == !!mute)
return;
-
+
*t = !!mute;
if (t == &s->hw_muted)
if (s->get_hw_mute)
s->get_hw_mute(s);
-
+
return s->hw_muted;
} else
return s->sw_muted;
if (description && s->description && !strcmp(description, s->description))
return;
-
+
pa_xfree(s->description);
s->description = pa_xstrdup(description);
if (s->monitor_source) {
char *n;
-
+
n = pa_sprintf_malloc("Monitor Source of %s", s->description? s->description : s->name);
pa_source_set_description(s->monitor_source, n);
pa_xfree(n);
}
-
+
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_idxset *inputs;
pa_source *monitor_source; /* may be NULL */
-
+
pa_cvolume hw_volume, sw_volume;
int hw_muted, sw_muted;
int (*get_hw_volume)(pa_sink *s); /* dito */
int (*set_hw_mute)(pa_sink *s); /* dito */
int (*get_hw_mute)(pa_sink *s); /* dito */
-
+
void *userdata;
};
void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result);
int pa_sink_render_into(pa_sink*s, pa_memchunk *target);
void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target);
-
+
pa_usec_t pa_sink_get_latency(pa_sink *s);
void pa_sink_notify(pa_sink*s);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
void pa_stdio_release(void) {
assert(stdio_inuse);
stdio_inuse = 0;
-}
+}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
static void free_events(pa_socket_client *c) {
assert(c);
-
+
if (c->io_event) {
c->mainloop->io_free(c->io_event);
c->io_event = NULL;
}
-
+
if (c->defer_event) {
c->mainloop->defer_free(c->defer_event);
c->defer_event = NULL;
}
-
+
if (c->timeout_event) {
c->mainloop->time_free(c->timeout_event);
c->timeout_event = NULL;
if (c->fd < 0)
goto finish;
-
+
lerror = sizeof(error);
if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &lerror) < 0) {
pa_log("getsockopt(): %s", pa_cstrerror(errno));
io = pa_iochannel_new(c->mainloop, c->fd, c->fd);
assert(io);
-
+
finish:
if (!io && c->fd >= 0)
close(c->fd);
c->fd = -1;
free_events(c);
-
+
assert(c->callback);
c->callback(c, io, c->userdata);
-
+
pa_socket_client_unref(c);
}
static int do_connect(pa_socket_client *c, const struct sockaddr *sa, socklen_t len) {
int r;
assert(c && sa && len);
-
+
pa_make_nonblock_fd(c->fd);
-
+
if ((r = connect(c->fd, sa, len)) < 0) {
#ifdef OS_IS_WIN32
if (WSAGetLastError() != EWOULDBLOCK) {
pa_socket_client* pa_socket_client_new_unix(pa_mainloop_api *m, const char *filename) {
struct sockaddr_un sa;
assert(m && filename);
-
+
memset(&sa, 0, sizeof(sa));
sa.sun_family = AF_UNIX;
strncpy(sa.sun_path, filename, sizeof(sa.sun_path)-1);
assert(c);
assert(sa);
assert(salen);
-
+
switch (sa->sa_family) {
case AF_UNIX:
c->local = 1;
break;
-
+
case AF_INET:
c->local = ((const struct sockaddr_in*) sa)->sin_addr.s_addr == INADDR_LOOPBACK;
break;
-
+
case AF_INET6:
c->local = memcmp(&((const struct sockaddr_in6*) sa)->sin6_addr, &in6addr_loopback, sizeof(struct in6_addr)) == 0;
break;
-
+
default:
c->local = 0;
}
-
+
if ((c->fd = socket(sa->sa_family, SOCK_STREAM, 0)) < 0) {
pa_log("socket(): %s", pa_cstrerror(errno));
return -1;
if (sockaddr_prepare(c, sa, salen) < 0)
goto fail;
-
+
return c;
fail:
pa_socket_client_unref(c);
return NULL;
-
+
}
static void socket_client_free(pa_socket_client *c) {
free_events(c);
-
+
if (c->fd >= 0)
close(c->fd);
if (c->asyncns_io_event)
c->mainloop->io_free(c->asyncns_io_event);
#endif
-
+
pa_xfree(c);
}
pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[16], uint16_t port) {
struct sockaddr_in6 sa;
-
+
memset(&sa, 0, sizeof(sa));
sa.sin6_family = AF_INET6;
sa.sin6_port = htons(port);
if (ret != 0 || !res)
goto fail;
-
+
if (res->ai_addr)
sockaddr_prepare(c, res->ai_addr, res->ai_addrlen);
-
+
asyncns_freeaddrinfo(res);
m->io_free(c->asyncns_io_event);
c->asyncns_io_event = NULL;
return;
-
+
fail:
m->io_free(c->asyncns_io_event);
c->asyncns_io_event = NULL;
-
+
errno = EHOSTUNREACH;
do_call(c);
return;
-
+
}
#endif
if (!a.port)
a.port = default_port;
-
+
switch (a.type) {
case PA_PARSED_ADDRESS_UNIX:
if ((c = pa_socket_client_new_unix(m, a.path_or_host)))
memset(&hints, 0, sizeof(hints));
hints.ai_family = a.type == PA_PARSED_ADDRESS_TCP4 ? PF_INET : (a.type == PA_PARSED_ADDRESS_TCP6 ? PF_INET6 : PF_UNSPEC);
hints.ai_socktype = SOCK_STREAM;
-
+
#ifdef HAVE_LIBASYNCNS
{
asyncns_t *asyncns;
-
+
if (!(asyncns = asyncns_new(1)))
goto finish;
struct addrinfo *res = NULL;
ret = getaddrinfo(a.path_or_host, port, &hints, &res);
-
+
if (ret < 0 || !res)
goto finish;
if ((c = pa_socket_client_new_sockaddr(m, res->ai_addr, res->ai_addrlen)))
start_timeout(c);
}
-
+
freeaddrinfo(res);
#else /* HAVE_GETADDRINFO */
struct hostent *host = NULL;
finish:
pa_xfree(a.path_or_host);
return c;
-
+
}
/* Return non-zero when the target sockaddr is considered
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
assert(s && s->mainloop == mainloop && s->io_event == e && e && fd >= 0 && fd == s->fd);
pa_socket_server_ref(s);
-
+
if ((nfd = accept(fd, NULL, NULL)) < 0) {
pa_log("accept(): %s", pa_cstrerror(errno));
goto finish;
}
pa_fd_set_cloexec(nfd, 1);
-
+
if (!s->on_connection) {
close(nfd);
goto finish;
pa_log_info("TCP connection accepted by tcpwrap.");
}
#endif
-
+
/* There should be a check for socket type here */
- if (s->type == SOCKET_SERVER_IPV4)
+ if (s->type == SOCKET_SERVER_IPV4)
pa_socket_tcp_low_delay(fd);
else
pa_socket_low_delay(fd);
-
+
io = pa_iochannel_new(s->mainloop, nfd, nfd);
assert(io);
s->on_connection(s, io, s->userdata);
pa_socket_server* pa_socket_server_new(pa_mainloop_api *m, int fd) {
pa_socket_server *s;
assert(m && fd >= 0);
-
+
s = pa_xmalloc(sizeof(pa_socket_server));
s->ref = 1;
s->fd = fd;
assert(s->io_event);
s->type = SOCKET_SERVER_GENERIC;
-
+
return s;
}
int fd = -1;
struct sockaddr_un sa;
pa_socket_server *s;
-
+
assert(m && filename);
if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
* because not all OS check the access rights on the socket
* inodes. */
chmod(filename, 0777);
-
+
if (listen(fd, 5) < 0) {
pa_log("listen(): %s", pa_cstrerror(errno));
goto fail;
s->filename = pa_xstrdup(filename);
s->type = SOCKET_SERVER_UNIX;
-
+
return s;
-
+
fail:
if (fd >= 0)
close(fd);
#endif
pa_socket_tcp_low_delay(fd);
-
+
memset(&sa, 0, sizeof(sa));
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
}
return ss;
-
+
fail:
if (fd >= 0)
close(fd);
ss->type = SOCKET_SERVER_IPV6;
ss->tcpwrap_service = pa_xstrdup(tcpwrap_service);
}
-
+
return ss;
-
+
fail:
if (fd >= 0)
close(fd);
pa_socket_server* pa_socket_server_new_ipv4_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) {
assert(m);
assert(port > 0);
-
+
return pa_socket_server_new_ipv4(m, INADDR_ANY, port, tcpwrap_service);
}
pa_socket_server* pa_socket_server_new_ipv6_any(pa_mainloop_api *m, uint16_t port, const char *tcpwrap_service) {
assert(m);
assert(port > 0);
-
+
return pa_socket_server_new_ipv6(m, in6addr_any.s6_addr, port, tcpwrap_service);
}
pa_socket_server* pa_socket_server_new_ipv4_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service) {
struct in_addr ipv4;
-
+
assert(m);
assert(name);
assert(port > 0);
pa_socket_server* pa_socket_server_new_ipv6_string(pa_mainloop_api *m, const char *name, uint16_t port, const char *tcpwrap_service) {
struct in6_addr ipv6;
-
+
assert(m);
assert(name);
assert(port > 0);
char *pa_socket_server_get_address(pa_socket_server *s, char *c, size_t l) {
assert(s && c && l > 0);
-
+
switch (s->type) {
case SOCKET_SERVER_IPV6: {
struct sockaddr_in6 sa;
char fqdn[256];
if (!pa_get_fqdn(fqdn, sizeof(fqdn)))
return NULL;
-
+
snprintf(c, l, "tcp6:%s:%u", fqdn, (unsigned) ntohs(sa.sin6_port));
-
+
} else if (memcmp(&in6addr_loopback, &sa.sin6_addr, sizeof(in6addr_loopback)) == 0) {
char hn[256];
if (!pa_get_host_name(hn, sizeof(hn)))
return NULL;
-
+
snprintf(c, l, "{%s}tcp6:localhost:%u", hn, (unsigned) ntohs(sa.sin6_port));
} else {
char ip[INET6_ADDRSTRLEN];
-
+
if (!inet_ntop(AF_INET6, &sa.sin6_addr, ip, sizeof(ip))) {
pa_log("inet_ntop(): %s", pa_cstrerror(errno));
return NULL;
}
-
+
snprintf(c, l, "tcp6:[%s]:%u", ip, (unsigned) ntohs(sa.sin6_port));
}
char fqdn[256];
if (!pa_get_fqdn(fqdn, sizeof(fqdn)))
return NULL;
-
+
snprintf(c, l, "tcp:%s:%u", fqdn, (unsigned) ntohs(sa.sin_port));
} else if (sa.sin_addr.s_addr == INADDR_LOOPBACK) {
char hn[256];
if (!pa_get_host_name(hn, sizeof(hn)))
return NULL;
-
+
snprintf(c, l, "{%s}tcp:localhost:%u", hn, (unsigned) ntohs(sa.sin_port));
} else {
char ip[INET_ADDRSTRLEN];
pa_log("inet_ntop(): %s", pa_cstrerror(errno));
return NULL;
}
-
+
snprintf(c, l, "tcp:[%s]:%u", ip, (unsigned) ntohs(sa.sin_port));
}
-
+
return c;
}
if (!s->filename)
return NULL;
-
+
if (!pa_get_host_name(hn, sizeof(hn)))
return NULL;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
struct stat st;
assert(c && l && fd >= 0);
-
+
#ifndef OS_IS_WIN32
if (fstat(fd, &st) < 0) {
snprintf(c, l, "Invalid client fd");
#ifndef OS_IS_WIN32
if (S_ISSOCK(st.st_mode)) {
-#endif
+#endif
union {
struct sockaddr sa;
struct sockaddr_in in;
#endif
} sa;
socklen_t sa_len = sizeof(sa);
-
+
if (getpeername(fd, &sa.sa, &sa_len) >= 0) {
if (sa.sa.sa_family == AF_INET) {
uint32_t ip = ntohl(sa.in.sin_addr.s_addr);
-
+
snprintf(c, l, "TCP/IP client from %i.%i.%i.%i:%u",
ip >> 24,
(ip >> 16) & 0xFF,
assert(fd >= 0);
ret = pa_socket_low_delay(fd);
-
+
on = 1;
tos = 0;
int pa_unix_socket_remove_stale(const char *fn) {
int r;
-
+
if ((r = pa_unix_socket_is_stale(fn)) < 0)
return errno != ENOENT ? -1 : 0;
if (!r)
return 0;
-
+
/* Yes, here is a race condition. But who cares? */
if (unlink(fn) < 0)
return -1;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_sink_input_disconnect(u->sink_input);
pa_sink_input_unref(u->sink_input);
}
-
+
if (u->memchunk.memblock)
pa_memblock_unref(u->memchunk.memblock);
if (u->sndfile)
} else {
if ((n = sf_read_raw(u->sndfile, u->memchunk.memblock->data, BUF_SIZE)) <= 0)
n = 0;
-
+
u->memchunk.length = n;
}
-
+
if (!u->memchunk.length) {
free_userdata(u);
return -1;
pa_sink *sink,
const char *fname,
const pa_cvolume *volume) {
-
+
struct userdata *u = NULL;
SF_INFO sfinfo;
pa_sample_spec ss;
pa_sink_input_new_data data;
-
+
assert(sink);
assert(fname);
}
u->readf_function = NULL;
-
+
switch (sfinfo.format & 0xFF) {
case SF_FORMAT_PCM_16:
case SF_FORMAT_PCM_U8:
case SF_FORMAT_ULAW:
ss.format = PA_SAMPLE_ULAW;
break;
-
+
case SF_FORMAT_ALAW:
ss.format = PA_SAMPLE_ALAW;
break;
u->readf_function = (sf_count_t (*)(SNDFILE *sndfile, void *ptr, sf_count_t frames)) sf_readf_float;
break;
}
-
+
ss.rate = sfinfo.samplerate;
ss.channels = sfinfo.channels;
data.name = fname;
pa_sink_input_new_data_set_sample_spec(&data, &ss);
pa_sink_input_new_data_set_volume(&data, volume);
-
+
if (!(u->sink_input = pa_sink_input_new(sink->core, &data, 0)))
goto fail;
u->sink_input->drop = sink_input_drop;
u->sink_input->kill = sink_input_kill;
u->sink_input->userdata = u;
-
+
pa_sink_notify(u->sink_input->sink);
return 0;
fail:
if (u)
free_userdata(u);
-
+
return -1;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
case SF_FORMAT_ULAW:
ss->format = PA_SAMPLE_ULAW;
break;
-
+
case SF_FORMAT_ALAW:
ss->format = PA_SAMPLE_ALAW;
break;
if (map)
pa_channel_map_init_auto(map, ss->channels, PA_CHANNEL_MAP_DEFAULT);
-
+
if ((l = pa_frame_size(ss)*sfinfo.frames) > PA_SCACHE_ENTRY_SIZE_MAX) {
pa_log("File too large");
goto finish;
pa_log("Premature file end");
goto finish;
}
-
+
ret = 0;
finish:
if (ret != 0 && chunk->memblock)
pa_memblock_unref(chunk->memblock);
-
+
return ret;
-
+
}
int pa_sound_file_too_big_to_cache(const char *fname) {
case SF_FORMAT_ULAW:
ss.format = PA_SAMPLE_ULAW;
break;
-
+
case SF_FORMAT_ALAW:
ss.format = PA_SAMPLE_ALAW;
break;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_source_output_new_data* pa_source_output_new_data_init(pa_source_output_new_data *data) {
assert(data);
-
+
memset(data, 0, sizeof(*data));
data->resample_method = PA_RESAMPLER_INVALID;
return data;
pa_core *core,
pa_source_output_new_data *data,
pa_source_output_flags_t flags) {
-
+
pa_source_output *o;
pa_resampler *resampler = NULL;
int r;
CHECK_VALIDITY_RETURN_NULL(data->source);
CHECK_VALIDITY_RETURN_NULL(data->source->state == PA_SOURCE_RUNNING);
-
+
if (!data->sample_spec_is_set)
data->sample_spec = data->source->sample_spec;
-
+
CHECK_VALIDITY_RETURN_NULL(pa_sample_spec_valid(&data->sample_spec));
if (!data->channel_map_is_set)
pa_channel_map_init_auto(&data->channel_map, data->sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
-
+
CHECK_VALIDITY_RETURN_NULL(pa_channel_map_valid(&data->channel_map));
CHECK_VALIDITY_RETURN_NULL(data->channel_map.channels == data->sample_spec.channels);
data->resample_method = core->resample_method;
CHECK_VALIDITY_RETURN_NULL(data->resample_method < PA_RESAMPLER_MAX);
-
+
if (pa_idxset_size(data->source->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) {
pa_log("Failed to create source output: too many outputs per source.");
return NULL;
pa_log_warn("Unsupported resampling operation.");
return NULL;
}
-
+
o = pa_xnew(pa_source_output, 1);
o->ref = 1;
o->state = PA_SOURCE_OUTPUT_RUNNING;
o->module = data->module;
o->source = data->source;
o->client = data->client;
-
+
o->sample_spec = data->sample_spec;
o->channel_map = data->channel_map;
o->kill = NULL;
o->get_latency = NULL;
o->userdata = NULL;
-
+
o->resampler = resampler;
o->resample_method = data->resample_method;
-
+
r = pa_idxset_put(core->source_outputs, o, &o->index);
assert(r == 0);
r = pa_idxset_put(o->source->outputs, o, NULL);
o->name,
o->source->name,
pa_sample_spec_snprint(st, sizeof(st), &o->sample_spec));
-
+
pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_NEW, o->index);
/* We do not call pa_source_notify() here, because the virtual
* functions have not yet been initialized */
-
- return o;
+
+ return o;
}
void pa_source_output_disconnect(pa_source_output*o) {
assert(o->state != PA_SOURCE_OUTPUT_DISCONNECTED);
assert(o->source);
assert(o->source->core);
-
+
pa_idxset_remove_by_data(o->source->core->source_outputs, o, NULL);
pa_idxset_remove_by_data(o->source->outputs, o, NULL);
o->push = NULL;
o->kill = NULL;
o->get_latency = NULL;
-
+
o->state = PA_SOURCE_OUTPUT_DISCONNECTED;
}
if (o->state != PA_SOURCE_OUTPUT_DISCONNECTED)
pa_source_output_disconnect(o);
- pa_log_info("freed %u \"%s\"", o->index, o->name);
-
+ pa_log_info("freed %u \"%s\"", o->index, o->name);
+
if (o->resampler)
pa_resampler_free(o->resampler);
pa_source_output* pa_source_output_ref(pa_source_output *o) {
assert(o);
assert(o->ref >= 1);
-
+
o->ref++;
return o;
}
void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
pa_memchunk rchunk;
-
+
assert(o);
assert(chunk);
assert(chunk->length);
if (o->state == PA_SOURCE_OUTPUT_CORKED)
return;
-
+
if (!o->resampler) {
o->push(o, chunk);
return;
pa_resampler_run(o->resampler, chunk, &rchunk);
if (!rchunk.length)
return;
-
+
assert(rchunk.memblock);
o->push(o, &rchunk);
pa_memblock_unref(rchunk.memblock);
if (o->name && name && !strcmp(o->name, name))
return;
-
+
pa_xfree(o->name);
o->name = pa_xstrdup(name);
pa_usec_t pa_source_output_get_latency(pa_source_output *o) {
assert(o);
assert(o->ref >= 1);
-
+
if (o->get_latency)
return o->get_latency(o);
void pa_source_output_cork(pa_source_output *o, int b) {
int n;
-
+
assert(o);
assert(o->ref >= 1);
return;
n = o->state == PA_SOURCE_OUTPUT_CORKED && !b;
-
+
o->state = b ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING;
-
+
if (n)
pa_source_notify(o->source);
}
pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o) {
assert(o);
assert(o->ref >= 1);
-
+
if (!o->resampler)
return o->resample_method;
/* Try to reuse the old resampler if possible */
new_resampler = o->resampler;
-
+
else if (!pa_sample_spec_equal(&o->sample_spec, &dest->sample_spec) ||
!pa_channel_map_equal(&o->channel_map, &dest->channel_map)) {
/* Okey, we need a new resampler for the new sink */
-
+
if (!(new_resampler = pa_resampler_new(
dest->core->mempool,
&dest->sample_spec, &dest->channel_map,
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
int ref;
uint32_t index;
pa_source_output_state_t state;
-
+
char *name, *driver; /* may be NULL */
pa_module *module; /* may be NULL */
pa_sample_spec sample_spec;
pa_channel_map channel_map;
-
+
void (*push)(pa_source_output *o, const pa_memchunk *chunk);
void (*kill)(pa_source_output* o); /* may be NULL */
pa_usec_t (*get_latency) (pa_source_output *o); /* may be NULL */
pa_resampler* resampler; /* may be NULL */
pa_resample_method_t resample_method;
-
+
void *userdata;
};
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
int fail,
const pa_sample_spec *spec,
const pa_channel_map *map) {
-
+
pa_source *s;
char st[256];
int r;
pa_channel_map tmap;
-
+
assert(core);
assert(name);
assert(spec);
s->description = NULL;
s->driver = pa_xstrdup(driver);
s->owner = NULL;
-
+
s->sample_spec = *spec;
s->channel_map = *map;
assert(s->index != PA_IDXSET_INVALID && r >= 0);
pa_sample_spec_snprint(st, sizeof(st), spec);
- pa_log_info("created %u \"%s\" with sample spec \"%s\"", s->index, s->name, st);
+ pa_log_info("created %u \"%s\" with sample spec \"%s\"", s->index, s->name, st);
pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_NEW, s->index);
-
+
return s;
}
void pa_source_disconnect(pa_source *s) {
pa_source_output *o, *j = NULL;
-
+
assert(s);
assert(s->state == PA_SOURCE_RUNNING);
pa_namereg_unregister(s->core, s->name);
pa_hook_fire(&s->core->hook_source_disconnect, s);
-
+
while ((o = pa_idxset_first(s->outputs, NULL))) {
assert(o != j);
pa_source_output_kill(o);
s->set_hw_volume = NULL;
s->set_hw_mute = NULL;
s->get_hw_mute = NULL;
-
+
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
}
static void source_free(pa_source *s) {
assert(s);
assert(!s->ref);
-
+
if (s->state != PA_SOURCE_DISCONNECTED)
pa_source_disconnect(s);
-
- pa_log_info("freed %u \"%s\"", s->index, s->name);
+
+ pa_log_info("freed %u \"%s\"", s->index, s->name);
pa_idxset_free(s->outputs, NULL, NULL);
pa_source* pa_source_ref(pa_source *s) {
assert(s);
assert(s->ref >= 1);
-
+
s->ref++;
return s;
}
static int do_post(void *p, PA_GCC_UNUSED uint32_t idx, PA_GCC_UNUSED int *del, void*userdata) {
pa_source_output *o = p;
const pa_memchunk *chunk = userdata;
-
+
assert(o);
assert(chunk);
if (s->sw_muted || !pa_cvolume_is_norm(&s->sw_volume)) {
pa_memchunk vchunk = *chunk;
-
+
pa_memblock_ref(vchunk.memblock);
pa_memchunk_make_writable(&vchunk, 0);
if (s->sw_muted)
if (m == s->owner)
return;
-
+
s->owner = m;
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
}
void pa_source_set_volume(pa_source *s, pa_mixer_t m, const pa_cvolume *volume) {
pa_cvolume *v;
-
+
assert(s);
assert(s->ref >= 1);
assert(volume);
- if (m == PA_MIXER_HARDWARE && s->set_hw_volume)
+ if (m == PA_MIXER_HARDWARE && s->set_hw_volume)
v = &s->hw_volume;
else
v = &s->sw_volume;
if (pa_cvolume_equal(v, volume))
return;
-
+
*v = *volume;
if (v == &s->hw_volume)
if (s->get_hw_volume)
s->get_hw_volume(s);
-
+
return &s->hw_volume;
} else
return &s->sw_volume;
void pa_source_set_mute(pa_source *s, pa_mixer_t m, int mute) {
int *t;
-
+
assert(s);
assert(s->ref >= 1);
- if (m == PA_MIXER_HARDWARE && s->set_hw_mute)
+ if (m == PA_MIXER_HARDWARE && s->set_hw_mute)
t = &s->hw_muted;
else
t = &s->sw_muted;
if (!!*t == !!mute)
return;
-
+
*t = !!mute;
if (t == &s->hw_muted)
if (s->get_hw_mute)
s->get_hw_mute(s);
-
+
return s->hw_muted;
} else
return s->sw_muted;
if (description && s->description && !strcmp(description, s->description))
return;
-
+
pa_xfree(s->description);
s->description = pa_xstrdup(description);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
uint32_t index;
pa_core *core;
pa_source_state_t state;
-
+
char *name;
char *description, *driver; /* may be NULL */
-
+
pa_module *owner; /* may be NULL */
pa_sample_spec sample_spec;
int hw_muted, sw_muted;
int is_hardware;
-
+
void (*notify)(pa_source*source); /* may be NULL */
pa_usec_t (*get_latency)(pa_source *s); /* dito */
int (*set_hw_volume)(pa_source *s); /* dito */
- int (*get_hw_volume)(pa_source *s); /* dito */
+ int (*get_hw_volume)(pa_source *s); /* dito */
int (*set_hw_mute)(pa_source *s); /* dito */
int (*get_hw_mute)(pa_source *s); /* dito */
-
+
void *userdata;
};
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
*e = 0;
assert(e == t+sb->length);
-
+
return t;
}
void pa_strbuf_putsn(pa_strbuf *sb, const char *t, size_t l) {
struct chunk *c;
assert(sb && t);
-
+
if (!l)
return;
-
+
c = pa_xmalloc(sizeof(struct chunk)+l);
c->length = l;
memcpy(CHUNK_TO_TEXT(c), t, l);
struct chunk *c = NULL;
assert(sb);
-
+
for(;;) {
va_list ap;
int r;
va_start(ap, format);
r = vsnprintf(CHUNK_TO_TEXT(c), size, format, ap);
va_end(ap);
-
+
if (r > -1 && r < size) {
c->length = r;
append(sb, c);
}
if (r > -1) /* glibc 2.1 */
- size = r+1;
+ size = r+1;
else /* glibc 2.0 */
size *= 2;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
while (l) {
if (!strcmp(l->str, s)) {
pa_strlist *n = l->next;
-
+
if (!prev) {
assert(ret == l);
ret = n;
pa_xfree(l);
l = n;
-
+
} else {
prev = l;
l = l->next;
pa_strlist* pa_strlist_pop(pa_strlist *l, char **s) {
pa_strlist *r;
assert(s);
-
+
if (!l) {
*s = NULL;
return NULL;
}
-
+
*s = l->str;
r = l->next;
pa_xfree(l);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_tagstruct*t;
assert(!data || (data && length));
-
+
t = pa_xmalloc(sizeof(pa_tagstruct));
t->data = (uint8_t*) data;
t->allocated = t->length = data ? length : 0;
t->dynamic = !data;
return t;
}
-
+
void pa_tagstruct_free(pa_tagstruct*t) {
assert(t);
if (t->dynamic)
void pa_tagstruct_put_channel_map(pa_tagstruct *t, const pa_channel_map *map) {
unsigned i;
-
+
assert(t);
extend(t, 2 + map->channels);
t->data[t->length++] = PA_TAG_CHANNEL_MAP;
t->data[t->length++] = map->channels;
-
+
for (i = 0; i < map->channels; i ++)
t->data[t->length++] = (uint8_t) map->map[i];
}
void pa_tagstruct_put_cvolume(pa_tagstruct *t, const pa_cvolume *cvolume) {
unsigned i;
pa_volume_t vol;
-
+
assert(t);
extend(t, 2 + cvolume->channels * sizeof(pa_volume_t));
t->data[t->length++] = PA_TAG_CVOLUME;
t->data[t->length++] = cvolume->channels;
-
+
for (i = 0; i < cvolume->channels; i ++) {
vol = htonl(cvolume->values[i]);
memcpy(t->data + t->length, &vol, sizeof(pa_volume_t));
*s = NULL;
return 0;
}
-
+
if (t->rindex+2 > t->length)
return -1;
-
+
if (t->data[t->rindex] != PA_TAG_STRING)
return -1;
if (t->data[t->rindex] != PA_TAG_SAMPLE_SPEC)
return -1;
-
+
ss->format = t->data[t->rindex+1];
ss->channels = t->data[t->rindex+2];
memcpy(&ss->rate, t->data+t->rindex+3, 4);
int pa_tagstruct_get_arbitrary(pa_tagstruct *t, const void **p, size_t length) {
uint32_t len;
assert(t && p);
-
+
if (t->rindex+5+length > t->length)
return -1;
*b = 0;
else
return -1;
-
+
t->rindex +=1;
return 0;
}
int pa_tagstruct_get_channel_map(pa_tagstruct *t, pa_channel_map *map) {
unsigned i;
-
+
assert(t);
assert(map);
if (t->rindex+2+map->channels > t->length)
return -1;
-
+
for (i = 0; i < map->channels; i ++)
map->map[i] = (int8_t) t->data[t->rindex + 2 + i];
int pa_tagstruct_get_cvolume(pa_tagstruct *t, pa_cvolume *cvolume) {
unsigned i;
pa_volume_t vol;
-
+
assert(t);
assert(cvolume);
if (t->rindex+2+cvolume->channels*sizeof(pa_volume_t) > t->length)
return -1;
-
+
for (i = 0; i < cvolume->channels; i ++) {
memcpy(&vol, t->data + t->rindex + 2 + i * sizeof(pa_volume_t), sizeof(pa_volume_t));
cvolume->values[i] = (pa_volume_t) ntohl(vol);
void pa_tagstruct_put(pa_tagstruct *t, ...) {
va_list va;
assert(t);
-
+
va_start(va, t);
for (;;) {
abort();
}
}
-
+
va_end(va);
}
int pa_tagstruct_get(pa_tagstruct *t, ...) {
va_list va;
int ret = 0;
-
+
assert(t);
-
+
va_start(va, t);
while (ret == 0) {
int tag = va_arg(va, int);
ret = pa_tagstruct_get_cvolume(t, va_arg(va, pa_cvolume *));
break;
-
+
default:
abort();
}
-
+
}
va_end(va);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_thread *t = p;
assert(t);
-
- if (!t->thread_func)
+
+ if (!t->thread_func)
/* This is a foreign thread, we need to free the struct */
pa_xfree(t);
}
t->id = pthread_self();
pa_once(&thread_tls_once, thread_tls_once_func);
-
+
pa_tls_set(thread_tls, t);
-
+
pa_atomic_inc(&t->running);
t->thread_func(t->userdata);
pa_atomic_add(&t->running, -2);
-
+
return NULL;
}
pa_thread *t;
assert(thread_func);
-
+
t = pa_xnew(pa_thread, 1);
t->thread_func = thread_func;
t->userdata = userdata;
int policy;
struct sched_param param;
-
+
return pthread_getschedparam(t->id, &policy, ¶m) >= 0 || errno != ESRCH;
}
void pa_thread_free(pa_thread *t) {
assert(t);
-
+
pa_thread_join(t);
pa_xfree(t);
}
int pa_thread_join(pa_thread *t) {
assert(t);
-
+
return pthread_join(t->id, NULL);
}
pa_thread* pa_thread_self(void) {
pa_thread *t;
-
+
pa_once(&thread_tls_once, thread_tls_once_func);
if ((t = pa_tls_get(thread_tls)))
/* This is a foreign thread, let's create a pthread structure to
* make sure that we can always return a sensible pointer */
-
+
t = pa_xnew(pa_thread, 1);
t->id = pthread_self();
t->thread_func = NULL;
pa_atomic_store(&t->running, 2);
pa_tls_set(thread_tls, t);
-
+
return t;
}
pa_xfree(t);
return NULL;
}
-
+
return t;
}
void *pa_tls_get(pa_tls *t) {
assert(t);
-
+
return pthread_getspecific(t->key);
}
void *pa_tls_set(pa_tls *t, void *userdata) {
void *r;
-
+
r = pthread_getspecific(t->key);
ASSERT_SUCCESS(pthread_setspecific(t->key, userdata));
return r;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_tokenizer* pa_tokenizer_new(const char *s, unsigned args) {
pa_tokenizer *t;
-
+
t = pa_xmalloc(sizeof(pa_tokenizer));
t->dynarray = pa_dynarray_new();
assert(t->dynarray);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
unsigned long nbytes_after;
unsigned char *prop = NULL;
char *ret = NULL;
-
+
Atom a = XInternAtom(d, name, False);
if (XGetWindowProperty(d, RootWindow(d, 0), a, 0, (l+2)/4, False, XA_STRING, &actual_type, &actual_format, &nitems, &nbytes_after, &prop) != Success)
goto finish;
if (prop)
XFree(prop);
-
+
return ret;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
struct pa_x11_wrapper {
pa_core *core;
int ref;
-
+
char *property_name;
Display *display;
/* Dispatch all pending X11 events */
static void work(pa_x11_wrapper *w) {
assert(w && w->ref >= 1);
-
+
while (XPending(w->display)) {
pa_x11_client *c;
XEvent e;
assert(m && e && w && w->ref >= 1);
m->defer_enable(e, 0);
-
+
work(w);
}
w->ref = 1;
w->property_name = pa_xstrdup(t);
w->display = d;
-
+
PA_LLIST_HEAD_INIT(pa_x11_client, w->clients);
PA_LLIST_HEAD_INIT(pa_x11_internal, w->internals);
w->io_event = c->mainloop->io_new(c->mainloop, ConnectionNumber(d), PA_IO_EVENT_INPUT, display_io_event, w);
XAddConnectionWatch(d, x11_watch, (XPointer) w);
-
+
r = pa_property_set(c, w->property_name, w);
assert(r >= 0);
-
+
return w;
}
XRemoveConnectionWatch(w->display, x11_watch, (XPointer) w);
XCloseDisplay(w->display);
-
+
w->core->mainloop->io_free(w->io_event);
w->core->mainloop->defer_free(w->defer_event);
while (w->internals)
x11_internal_remove(w, w->internals);
-
+
pa_xfree(w->property_name);
pa_xfree(w);
}
char t[256];
pa_x11_wrapper *w;
assert(c);
-
+
snprintf(t, sizeof(t), "x11-wrapper%s%s", name ? "-" : "", name ? name : "");
if ((w = pa_property_get(c, t)))
return pa_x11_wrapper_ref(w);
/* Somebody is using us, schedule a output buffer flush */
w->core->mainloop->defer_enable(w->defer_event, 1);
-
+
return w->display;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_channel_map map, map2;
pa_channel_map_init_auto(&map, 6, PA_CHANNEL_MAP_AIFF);
-
+
fprintf(stderr, "map: <%s>\n", pa_channel_map_snprint(cm, sizeof(cm), &map));
pa_channel_map_init_auto(&map, 6, PA_CHANNEL_MAP_AUX);
-
+
fprintf(stderr, "map: <%s>\n", pa_channel_map_snprint(cm, sizeof(cm), &map));
pa_channel_map_init_auto(&map, 6, PA_CHANNEL_MAP_ALSA);
-
+
fprintf(stderr, "map: <%s>\n", pa_channel_map_snprint(cm, sizeof(cm), &map));
-
+
pa_channel_map_parse(&map2, cm);
assert(pa_channel_map_equal(&map, &map2));
pa_channel_map_parse(&map2, "left,test");
-
+
return 0;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
static void func(pa_mainloop_api *m, PA_GCC_UNUSED pa_signal_event *e, PA_GCC_UNUSED int sig, PA_GCC_UNUSED void *userdata) {
time_t now;
time(&now);
-
+
if ((now - start) >= 30) {
m->quit(m, 1);
fprintf(stderr, "Test failed\n");
int main(PA_GCC_UNUSED int argc, PA_GCC_UNUSED char *argv[]) {
pa_mainloop *m;
-
+
m = pa_mainloop_new();
assert(m);
for (;;) {
time_t now;
time(&now);
-
+
if ((now - start) >= 30) {
fprintf(stderr, "Test failed\n");
break;
#endif
pa_cpu_limit_done();
-
+
pa_mainloop_free(m);
return 0;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
static void spin(void) {
int k;
-
+
/* Spin a little */
k = rand() % 10000;
for (; k > 0; k--)
pa_thread_free(threads[i]);
pa_flist_free(flist, pa_xfree);
-
+
return 0;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_hook_connect(&hook, (pa_hook_cb_t) func1, (void*) "slot1");
slot = pa_hook_connect(&hook, (pa_hook_cb_t) func2, (void*) "slot2");
pa_hook_connect(&hook, (pa_hook_cb_t) func1, (void*) "slot3");
-
+
pa_hook_fire(&hook, (void*) "call1");
pa_hook_slot_free(slot);
pa_hook_fire(&hook, (void*) "call2");
pa_hook_free(&hook);
-
+
return 0;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
case PA_CONTEXT_AUTHORIZING:
case PA_CONTEXT_SETTING_NAME:
break;
-
+
case PA_CONTEXT_READY: {
static const pa_sample_spec ss = {
.rate = 44100,
.channels = 1
};
-
+
fprintf(stderr, "Connection established.\n");
stream = pa_stream_new(c, "interpol-test", &ss, NULL);
assert(stream);
-
+
pa_stream_connect_playback(stream, NULL, NULL, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL);
pa_stream_set_write_callback(stream, stream_write_cb, NULL);
-
+
break;
}
-
+
case PA_CONTEXT_TERMINATED:
break;
assert(r >= 0);
pa_gettimeofday(&start);
-
+
pa_threaded_mainloop_start(m);
for (k = 0; k < 5000; k++) {
int success = 0, changed = 0;
pa_usec_t t, rtc;
struct timeval now, tv;
-
+
pa_threaded_mainloop_lock(m);
if (stream) {
const pa_timing_info *info;
-
+
if (pa_stream_get_time(stream, &t) >= 0)
success = 1;
last_info = info->timestamp;
}
}
-
+
pa_threaded_mainloop_unlock(m);
-
+
if (success) {
pa_gettimeofday(&now);
pa_stream_disconnect(stream);
pa_stream_unref(stream);
}
-
+
if (context) {
pa_context_disconnect(context);
pa_context_unref(context);
if (m)
pa_threaded_mainloop_free(m);
-
+
return 0;
}
int r;
pa_ip_acl *acl;
- fd = socket(PF_INET, SOCK_STREAM, 0);
+ fd = socket(PF_INET, SOCK_STREAM, 0);
assert(fd >= 0);
-
+
sa.sin_family = AF_INET;
sa.sin_port = htons(22);
sa.sin_addr.s_addr = inet_addr("127.0.0.1");
-
+
r = connect(fd, (struct sockaddr*) &sa, sizeof(sa));
assert(r >= 0);
assert(acl);
printf("result=%u (should be 1)\n", pa_ip_acl_check(acl, fd));
pa_ip_acl_free(acl);
-
+
acl = pa_ip_acl_new("127.0.0.2");
assert(acl);
printf("result=%u (should be 0)\n", pa_ip_acl_check(acl, fd));
assert(acl);
printf("result=%u (should be 0)\n", pa_ip_acl_check(acl, fd));
pa_ip_acl_free(acl);
-
+
close(fd);
fd = socket(PF_INET6, SOCK_STREAM, 0);
sa6.sin6_family = AF_INET6;
sa6.sin6_port = htons(22);
inet_pton(AF_INET6, "::1", &sa6.sin6_addr);
-
+
r = connect(fd, (struct sockaddr*) &sa6, sizeof(sa6));
assert(r >= 0);
pa_ip_acl_free(acl);
close(fd);
-
+
return 0;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
#else
pa_mainloop_free(m);
#endif
-
+
return 0;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
p = pa_mempool_new(0);
a = pa_mcalign_new(11);
-
+
pa_memchunk_reset(&c);
srand(time(NULL));
l = c.memblock->length - c.index;
l = l <= 1 ? l : rand() % (l-1) +1 ;
-
+
if ((r = read(STDIN_FILENO, (uint8_t*) c.memblock->data + c.index, l)) <= 0) {
fprintf(stderr, "read() failed: %s\n", r < 0 ? strerror(errno) : "EOF");
break;
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
size_t offset, size;
const char txt[] = "This is a test!";
-
+
pool_a = pa_mempool_new(1);
pool_b = pa_mempool_new(1);
pool_c = pa_mempool_new(1);
pa_mempool_get_shm_id(pool_a, &id_a);
pa_mempool_get_shm_id(pool_b, &id_b);
pa_mempool_get_shm_id(pool_c, &id_c);
-
+
assert(pool_a && pool_b && pool_c);
-
+
blocks[0] = pa_memblock_new_fixed(pool_a, (void*) txt, sizeof(txt), 1);
blocks[1] = pa_memblock_new(pool_a, sizeof(txt));
snprintf(blocks[1]->data, blocks[1]->length, "%s", txt);
mb_a = blocks[i];
assert(mb_a);
-
+
export_a = pa_memexport_new(pool_a, revoke_cb, (void*) "A");
export_b = pa_memexport_new(pool_b, revoke_cb, (void*) "B");
-
+
assert(export_a && export_b);
-
+
import_b = pa_memimport_new(pool_b, release_cb, (void*) "B");
import_c = pa_memimport_new(pool_c, release_cb, (void*) "C");
-
+
assert(import_b && import_c);
-
+
r = pa_memexport_put(export_a, mb_a, &id, &shm_id, &offset, &size);
assert(r >= 0);
assert(shm_id == id_a);
printf("A: Memory block exported as %u\n", id);
-
+
mb_b = pa_memimport_get(import_b, id, shm_id, offset, size);
assert(mb_b);
r = pa_memexport_put(export_b, mb_b, &id, &shm_id, &offset, &size);
pa_memblock_unref(mb_b);
printf("B: Memory block exported as %u\n", id);
-
+
mb_c = pa_memimport_get(import_c, id, shm_id, offset, size);
assert(mb_c);
printf("1 data=%s\n", (char*) mb_c->data);
print_stats(pool_a, "A");
print_stats(pool_b, "B");
print_stats(pool_c, "C");
-
+
pa_memexport_free(export_b);
printf("2 data=%s\n", (char*) mb_c->data);
pa_memblock_unref(mb_c);
-
+
pa_memimport_free(import_b);
-
+
pa_memblock_unref(mb_a);
-
+
pa_memimport_free(import_c);
pa_memexport_free(export_a);
}
printf("vaccuuming...\n");
-
+
pa_mempool_vacuum(pool_a);
pa_mempool_vacuum(pool_b);
pa_mempool_vacuum(pool_c);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_log_set_maximal_level(PA_LOG_DEBUG);
p = pa_mempool_new(0);
-
+
silence = pa_memblock_new_fixed(p, (char*) "__", 2, 1);
assert(silence);
chunk1.index = 0;
chunk1.length = 2;
assert(chunk1.memblock);
-
+
chunk2.memblock = pa_memblock_new_fixed(p, (char*) "TTBB", 4, 1);
chunk2.index = 2;
chunk2.length = 2;
ret = pa_memblockq_push(bq, &chunk1);
assert(ret == 0);
-
+
ret = pa_memblockq_push(bq, &chunk1);
assert(ret == 0);
-
+
ret = pa_memblockq_push(bq, &chunk2);
assert(ret == 0);
-
+
ret = pa_memblockq_push(bq, &chunk2);
assert(ret == 0);
chunk3.index += 2;
chunk3.length -= 2;
-
+
ret = pa_memblockq_push(bq, &chunk3);
assert(ret == 0);
-
+
printf(">");
pa_memblockq_shorten(bq, 6);
-
+
for (;;) {
pa_memchunk out;
char *e;
size_t n;
-
+
if (pa_memblockq_peek(bq, &out) < 0)
break;
pa_memblock_unref(out.memblock);
pa_memblockq_drop(bq, &out, out.length);
}
-
+
printf("<\n");
-
+
pa_memblockq_free(bq);
pa_memblock_unref(silence);
pa_memblock_unref(chunk1.memblock);
pa_memblock_unref(chunk2.memblock);
pa_memblock_unref(chunk3.memblock);
pa_memblock_unref(chunk4.memblock);
-
+
return 0;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
.rate = 44100,
.channels = 2
};
-
+
pa_simple *s = NULL;
int ret = 1;
int error;
fprintf(stderr, __FILE__": dup2() failed: %s\n", strerror(errno));
goto finish;
}
-
+
close(fd);
}
-
+
/* Create a new playback stream */
if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, NULL, &error))) {
fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
if ((r = read(STDIN_FILENO, buf, sizeof(buf))) <= 0) {
if (r == 0) /* EOF */
break;
-
+
fprintf(stderr, __FILE__": read() failed: %s\n", strerror(errno));
goto finish;
}
if (s)
pa_simple_free(s);
-
+
return ret;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
if (r == 0)
break;
-
+
ret += r;
data = (const uint8_t*) data + r;
size -= r;
if (s)
pa_simple_free(s);
-
+
return ret;
}
t = pa_strlist_tostring(l);
pa_strlist_free(l);
-
+
fprintf(stderr, "1: %s\n", t);
l = pa_strlist_parse(t);
l = pa_strlist_pop(l, &u);
fprintf(stderr, "3: %s\n", u);
pa_xfree(u);
-
+
l = pa_strlist_remove(l, "c");
-
+
t = pa_strlist_tostring(l);
fprintf(stderr, "4: %s\n", t);
pa_xfree(t);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
int i = (int) (long) userdata;
fprintf(stderr, "Stream %i finished\n", i);
-
+
if (++n_streams_ready >= 2*NSTREAMS) {
fprintf(stderr, "We're done\n");
mainloop_api->quit(mainloop_api, 0);
int r, i = (int) (long) userdata;
fprintf(stderr, "Writing data to stream %i.\n", i);
-
+
r = pa_stream_write(s, data, sizeof(data), nop_free_cb, sizeof(data) * i, PA_SEEK_ABSOLUTE);
assert(r == 0);
/* Be notified when this stream is drained */
pa_stream_set_underflow_callback(s, underflow_cb, userdata);
-
+
/* All streams have been set up, let's go! */
if (++n_streams_ready >= NSTREAMS) {
fprintf(stderr, "Uncorking\n");
pa_operation_unref(pa_stream_cork(s, 0, NULL, NULL));
}
-
+
break;
}
case PA_CONTEXT_AUTHORIZING:
case PA_CONTEXT_SETTING_NAME:
break;
-
+
case PA_CONTEXT_READY: {
int i;
char name[64];
fprintf(stderr, "Creating stream %i\n", i);
-
+
snprintf(name, sizeof(name), "stream #%i", i);
-
+
streams[i] = pa_stream_new(c, name, &sample_spec, NULL);
assert(streams[i]);
pa_stream_set_state_callback(streams[i], stream_state_callback, (void*) (long) i);
pa_stream_connect_playback(streams[i], NULL, &buffer_attr, PA_STREAM_START_CORKED, NULL, i == 0 ? NULL : streams[0]);
}
-
+
break;
}
-
+
case PA_CONTEXT_TERMINATED:
mainloop_api->quit(mainloop_api, 0);
break;
for (i = 0; i < NSTREAMS; i++)
streams[i] = NULL;
-
+
/* Set up a new main loop */
m = pa_mainloop_new();
assert(m);
pa_stream_unref(streams[i]);
pa_mainloop_free(m);
-
+
return ret;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_threaded_mainloop_start(m);
pa_threaded_mainloop_lock(m);
-
+
pa_gettimeofday(&tv);
tv.tv_sec += 5;
a->time_new(a, &tv, tcb, m);
-
+
fprintf(stderr, "waiting 5s (signal)\n");
pa_threaded_mainloop_wait(m);
fprintf(stderr, "wait completed\n");
pa_threaded_mainloop_accept(m);
fprintf(stderr, "signal accepted\n");
-
+
pa_threaded_mainloop_unlock(m);
-
+
fprintf(stderr, "waiting 5s (sleep)\n");
pa_msleep(5000);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_tls_set(tls, data);
pa_log("thread_func() for %s starting...", (char*) pa_tls_get(tls));
-
+
pa_mutex_lock(mutex);
for (;;) {
pa_log("%s waiting ...", (char*) pa_tls_get(tls));
for (;;) {
-
+
if (magic_number < 0)
goto quit;
if (magic_number != 0)
break;
-
+
pa_cond_wait(cond1, mutex);
}
pa_once(&once, once_func);
pa_cond_signal(cond2, 0);
-
+
pa_log("%s got number %i", (char*) pa_tls_get(tls), k);
-
+
/* Spin! */
for (n = 0; n < k; n++)
pa_thread_yield();
-
+
pa_mutex_lock(mutex);
}
quit:
-
+
pa_mutex_unlock(mutex);
pa_log("thread_func() for %s done...", (char*) pa_tls_get(tls));
pa_thread* t[THREADS_MAX];
assert(pa_thread_is_running(pa_thread_self()));
-
+
mutex = pa_mutex_new(0);
cond1 = pa_cond_new();
cond2 = pa_cond_new();
tls = pa_tls_new(pa_xfree);
-
+
for (i = 0; i < THREADS_MAX; i++) {
t[i] = pa_thread_new(thread_func, pa_sprintf_malloc("Thread #%i", i+1));
assert(t[i]);
}
pa_mutex_lock(mutex);
-
+
pa_log("loop-init");
for (k = 0; k < 100; k++) {
assert(magic_number == 0);
-
+
magic_number = (int) rand() % 0x10000;
pa_log("iteration %i (%i)", k, magic_number);
}
pa_log("loop-exit");
-
+
magic_number = -1;
pa_cond_signal(cond1, 1);
-
+
pa_mutex_unlock(mutex);
for (i = 0; i < THREADS_MAX; i++)
int main(int argc, char *argv[]) {
char *c;
-
+
assert(pa_utf8_valid("hallo"));
assert(pa_utf8_valid("hallo\n"));
assert(!pa_utf8_valid("hüpfburg\n"));
assert(pa_utf8_valid("hallo\n"));
assert(pa_utf8_valid("hüpfburg\n"));
-
+
printf("LATIN1: %s\n", c = pa_utf8_filter("hüpfburg"));
pa_xfree(c);
printf("UTF8: %sx\n", c = pa_utf8_filter("hüpfburg"));
double dB = pa_sw_volume_to_dB(v);
double f = pa_sw_volume_to_linear(v);
-
+
printf("Volume: %3i; percent: %i%%; decibel %0.2f; linear = %0.2f; volume(decibel): %3i; volume(linear): %3i\n",
v, (v*100)/PA_VOLUME_NORM, dB, f, pa_sw_volume_from_dB(dB), pa_sw_volume_from_linear(f));
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
if (i->cookie)
snprintf(t, sizeof(t), "0x%08x", *i->cookie);
-
+
printf("server: %s\n"
"server-version: %s\n"
"user-name: %s\n"
i->device,
i->description ? i->description : "n/a",
i->sample_spec ? ss : "n/a");
-
+
}
static void browser_callback(pa_browser *b, pa_browse_opcode_t c, const pa_browse_info *i, void *userdata) {
dump_server(i);
dump_device(i);
break;
-
+
case PA_BROWSE_REMOVE_SERVER:
printf("\n=> removed server <%s>\n", i->name);
break;
static void error_callback(pa_browser *b, const char *s, void *userdata) {
pa_mainloop_api*m = userdata;
-
+
fprintf(stderr, "Failure: %s\n", s);
m->quit(m, 1);
}
pa_signal_new(SIGINT, exit_signal_callback, NULL);
pa_signal_new(SIGTERM, exit_signal_callback, NULL);
signal(SIGPIPE, SIG_IGN);
-
+
if (!(browser = pa_browser_new_full(pa_mainloop_get_api(mainloop), PA_BROWSE_FOR_SERVERS|PA_BROWSE_FOR_SINKS|PA_BROWSE_FOR_SOURCES, &s))) {
fprintf(stderr, "pa_browse_new_full(): %s\n", s);
goto finish;
pa_browser_set_callback(browser, browser_callback, NULL);
pa_browser_set_error_callback(browser, error_callback, pa_mainloop_get_api(mainloop));
-
+
ret = 0;
pa_mainloop_run(mainloop, &ret);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
if (!buffer || !buffer_length)
return;
-
+
l = length;
if (l > buffer_length)
l = buffer_length;
-
+
if (pa_stream_write(stream, (uint8_t*) buffer + buffer_index, l, NULL, 0, PA_SEEK_RELATIVE) < 0) {
fprintf(stderr, "pa_stream_write() failed: %s\n", pa_strerror(pa_context_errno(context)));
quit(1);
return;
}
-
+
buffer_length -= l;
buffer_index += l;
-
+
if (!buffer_length) {
pa_xfree(buffer);
buffer = NULL;
quit(1);
return;
}
-
+
assert(data && length);
if (buffer) {
case PA_STREAM_READY:
if (verbose) {
const pa_buffer_attr *a;
-
+
fprintf(stderr, "Stream successfully created.\n");
if (!(a = pa_stream_get_buffer_attr(s)))
assert(mode == RECORD);
fprintf(stderr, "Buffer metrics: maxlength=%u, fragsize=%u\n", a->maxlength, a->fragsize);
}
-
+
}
}
-
+
break;
-
+
case PA_STREAM_FAILED:
default:
fprintf(stderr, "Stream error: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s))));
case PA_CONTEXT_AUTHORIZING:
case PA_CONTEXT_SETTING_NAME:
break;
-
+
case PA_CONTEXT_READY: {
int r;
-
+
assert(c && !stream);
if (verbose)
fprintf(stderr, "pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(c)));
goto fail;
}
-
+
} else {
if ((r = pa_stream_connect_record(stream, device, NULL, 0)) < 0) {
fprintf(stderr, "pa_stream_connect_record() failed: %s\n", pa_strerror(pa_context_errno(c)));
goto fail;
}
}
-
+
break;
}
-
+
case PA_CONTEXT_TERMINATED:
quit(0);
break;
}
return;
-
+
fail:
quit(1);
-
+
}
/* Connection draining complete */
fprintf(stderr, "Failed to drain stream: %s\n", pa_strerror(pa_context_errno(context)));
quit(1);
}
-
- if (verbose)
+
+ if (verbose)
fprintf(stderr, "Playback stream drained.\n");
pa_stream_disconnect(stream);
pa_stream_unref(stream);
stream = NULL;
-
+
if (!(o = pa_context_drain(context, context_drain_complete, NULL)))
pa_context_disconnect(context);
else {
if (!stream || pa_stream_get_state(stream) != PA_STREAM_READY || !(l = w = pa_stream_writable_size(stream)))
l = 4096;
-
+
buffer = pa_xmalloc(l);
if ((r = read(fd, buffer, l)) <= 0) {
if (stream) {
pa_operation *o;
-
+
if (!(o = pa_stream_drain(stream, stream_drain_complete, NULL))) {
fprintf(stderr, "pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(context)));
quit(1);
return;
}
-
+
pa_operation_unref(o);
} else
quit(0);
-
+
} else {
fprintf(stderr, "read() failed: %s\n", strerror(errno));
quit(1);
}
assert(buffer_length);
-
+
if ((r = write(fd, (uint8_t*) buffer+buffer_index, buffer_length)) <= 0) {
fprintf(stderr, "write() failed: %s\n", strerror(errno));
quit(1);
static void stream_update_timing_callback(pa_stream *s, int success, void *userdata) {
pa_usec_t latency, usec;
int negative = 0;
-
+
assert(s);
if (!success ||
if (!stream)
return;
-
+
pa_operation_unref(pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL));
}
static void time_event_callback(pa_mainloop_api*m, pa_time_event *e, const struct timeval *tv, void *userdata) {
struct timeval next;
-
+
if (stream && pa_stream_get_state(stream) == PA_STREAM_READY) {
pa_operation *o;
if (!(o = pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL)))
help(bn);
ret = 0;
goto quit;
-
+
case ARG_VERSION:
printf("pacat "PACKAGE_VERSION"\nCompiled with libpulse %s\nLinked with libpulse %s\n", pa_get_headers_version(), pa_get_library_version());
ret = 0;
break;
}
- case ARG_CHANNELS:
+ case ARG_CHANNELS:
sample_spec.channels = atoi(optarg);
break;
channel_map_set = 1;
break;
-
+
default:
goto quit;
}
fprintf(stderr, "Channel map doesn't match sample specification\n");
goto quit;
}
-
+
if (verbose) {
char t[PA_SAMPLE_SPEC_SNPRINT_MAX];
pa_sample_spec_snprint(t, sizeof(t), &sample_spec);
if (!(optind >= argc)) {
if (optind+1 == argc) {
int fd;
-
+
if ((fd = open(argv[optind], mode == PLAYBACK ? O_RDONLY : O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) {
fprintf(stderr, "open(): %s\n", strerror(errno));
goto quit;
}
-
+
if (dup2(fd, mode == PLAYBACK ? 0 : 1) < 0) {
fprintf(stderr, "dup2(): %s\n", strerror(errno));
goto quit;
}
-
+
close(fd);
if (!stream_name)
stream_name = pa_xstrdup(argv[optind]);
-
+
} else {
fprintf(stderr, "Too many arguments.\n");
goto quit;
#ifdef SIGPIPE
signal(SIGPIPE, SIG_IGN);
#endif
-
+
if (!(stdio_event = mainloop_api->io_new(mainloop_api,
mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO,
mode == PLAYBACK ? PA_IO_EVENT_INPUT : PA_IO_EVENT_OUTPUT,
pa_gettimeofday(&tv);
pa_timeval_add(&tv, TIME_EVENT_USEC);
-
+
if (!(time_event = mainloop_api->time_new(mainloop_api, &tv, time_event_callback, NULL))) {
fprintf(stderr, "time_new() failed.\n");
goto quit;
fprintf(stderr, "pa_mainloop_run() failed.\n");
goto quit;
}
-
+
quit:
if (stream)
pa_stream_unref(stream);
assert(mainloop_api);
mainloop_api->time_free(time_event);
}
-
+
if (m) {
pa_signal_done();
pa_mainloop_free(m);
pa_xfree(device);
pa_xfree(client_name);
pa_xfree(stream_name);
-
+
return ret;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
for (i = 0; i < 5; i++) {
int r;
-
+
if ((r = connect(fd, (struct sockaddr*) &sa, sizeof(sa))) < 0 && (errno != ECONNREFUSED && errno != ENOENT)) {
pa_log("connect(): %s", strerror(errno));
goto fail;
}
-
+
if (r >= 0)
break;
FD_SET(fd, &ifds);
FD_ZERO(&ofds);
-
+
for (;;) {
if (select(FD_SETSIZE, &ifds, &ofds, NULL, NULL) < 0) {
pa_log("select(): %s", strerror(errno));
if (FD_ISSET(0, &ifds)) {
ssize_t r;
assert(!ibuf_length);
-
+
if ((r = read(0, ibuf, sizeof(ibuf))) <= 0) {
if (r == 0)
break;
-
+
pa_log("read(): %s", strerror(errno));
goto fail;
}
-
+
ibuf_length = (size_t) r;
ibuf_index = 0;
}
-
+
if (FD_ISSET(fd, &ifds)) {
ssize_t r;
assert(!obuf_length);
if ((r = read(fd, obuf, sizeof(obuf))) <= 0) {
if (r == 0)
break;
-
+
pa_log("read(): %s", strerror(errno));
goto fail;
}
if (FD_ISSET(1, &ofds)) {
ssize_t r;
assert(obuf_length);
-
+
if ((r = write(1, obuf + obuf_index, obuf_length)) < 0) {
pa_log("write(): %s", strerror(errno));
goto fail;
}
-
+
obuf_length -= (size_t) r;
obuf_index += obuf_index;
if (FD_ISSET(fd, &ofds)) {
ssize_t r;
assert(ibuf_length);
-
+
if ((r = write(fd, ibuf + ibuf_index, ibuf_length)) < 0) {
pa_log("write(): %s", strerror(errno));
goto fail;
}
-
+
ibuf_length -= (size_t) r;
ibuf_index += obuf_index;
FD_ZERO(&ifds);
FD_ZERO(&ofds);
-
+
if (obuf_length <= 0)
FD_SET(fd, &ifds);
else
FD_SET(1, &ofds);
-
+
if (ibuf_length <= 0)
FD_SET(0, &ifds);
else
FD_SET(fd, &ofds);
}
-
+
ret = 0;
-
+
fail:
if (fd >= 0)
close(fd);
-
+
return ret;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pa_bytes_snprint(s, sizeof(s), i->scache_size);
printf("Sample cache size: %s\n", s);
-
+
complete_action();
}
static void get_server_info_callback(pa_context *c, const pa_server_info *i, void *useerdata) {
char s[PA_SAMPLE_SPEC_SNPRINT_MAX];
-
+
if (!i) {
fprintf(stderr, "Failed to get server information: %s\n", pa_strerror(pa_context_errno(c)));
quit(1);
static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_last, void *userdata) {
char s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
-
+
if (is_last < 0) {
fprintf(stderr, "Failed to get sink information: %s\n", pa_strerror(pa_context_errno(c)));
quit(1);
complete_action();
return;
}
-
+
assert(i);
if (nl)
complete_action();
return;
}
-
+
assert(i);
if (nl)
nl = 1;
snprintf(t, sizeof(t), "%u", i->monitor_of_sink);
-
+
printf("*** Source #%u ***\n"
"Name: %s\n"
"Driver: %s\n"
complete_action();
return;
}
-
+
assert(i);
if (nl)
nl = 1;
snprintf(t, sizeof(t), "%u", i->n_used);
-
+
printf("*** Module #%u ***\n"
"Name: %s\n"
"Argument: %s\n"
complete_action();
return;
}
-
+
assert(i);
if (nl)
nl = 1;
snprintf(t, sizeof(t), "%u", i->owner_module);
-
+
printf("*** Client #%u ***\n"
"Name: %s\n"
"Driver: %s\n"
complete_action();
return;
}
-
+
assert(i);
if (nl)
snprintf(t, sizeof(t), "%u", i->owner_module);
snprintf(k, sizeof(k), "%u", i->client);
-
+
printf("*** Sink Input #%u ***\n"
"Name: %s\n"
"Driver: %s\n"
complete_action();
return;
}
-
+
assert(i);
if (nl)
printf("\n");
nl = 1;
-
+
snprintf(t, sizeof(t), "%u", i->owner_module);
snprintf(k, sizeof(k), "%u", i->client);
-
+
printf("*** Source Output #%u ***\n"
"Name: %s\n"
"Driver: %s\n"
complete_action();
return;
}
-
+
assert(i);
if (nl)
printf("\n");
nl = 1;
-
+
pa_bytes_snprint(t, sizeof(t), i->bytes);
-
+
printf("*** Sample #%u ***\n"
"Name: %s\n"
"Volume: %s\n"
complete_action();
return;
}
-
+
assert(i);
if (nl)
case PA_STREAM_CREATING:
case PA_STREAM_READY:
break;
-
+
case PA_STREAM_TERMINATED:
drain();
break;
-
+
case PA_STREAM_FAILED:
default:
fprintf(stderr, "Failed to upload sample: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s))));
fprintf(stderr, "Premature end of file\n");
quit(1);
}
-
+
pa_stream_write(s, d, length, pa_xfree, 0, PA_SEEK_RELATIVE);
sample_length -= length;
pa_operation_unref(pa_context_get_server_info(c, get_server_info_callback, NULL));
break;
- case PLAY_SAMPLE:
+ case PLAY_SAMPLE:
pa_operation_unref(pa_context_play_sample(c, sample_name, device, PA_VOLUME_NORM, simple_callback, NULL));
break;
case UPLOAD_SAMPLE:
sample_stream = pa_stream_new(c, sample_name, &sample_spec, NULL);
assert(sample_stream);
-
+
pa_stream_set_state_callback(sample_stream, stream_state_callback, NULL);
pa_stream_set_write_callback(sample_stream, stream_write_callback, NULL);
pa_stream_connect_upload(sample_stream, sample_length);
break;
-
+
case EXIT:
pa_operation_unref(pa_context_exit_daemon(c, NULL, NULL));
drain();
pa_operation_unref(pa_context_get_sink_info_list(c, get_sink_info_callback, NULL));
pa_operation_unref(pa_context_get_source_info_list(c, get_source_info_callback, NULL));
pa_operation_unref(pa_context_get_sink_input_info_list(c, get_sink_input_info_callback, NULL));
- pa_operation_unref(pa_context_get_source_output_info_list(c, get_source_output_info_callback, NULL));
+ pa_operation_unref(pa_context_get_source_output_info_list(c, get_source_output_info_callback, NULL));
pa_operation_unref(pa_context_get_client_info_list(c, get_client_info_callback, NULL));
pa_operation_unref(pa_context_get_sample_info_list(c, get_sample_info_callback, NULL));
pa_operation_unref(pa_context_get_autoload_info_list(c, get_autoload_info_callback, NULL));
case MOVE_SOURCE_OUTPUT:
pa_operation_unref(pa_context_move_source_output_by_name(c, source_output_idx, source_name, simple_callback, NULL));
break;
-
+
default:
assert(0);
}
bn = argv[0];
else
bn++;
-
+
while ((c = getopt_long(argc, argv, "s:n:h", long_options, NULL)) != -1) {
switch (c) {
case 'h' :
help(bn);
ret = 0;
goto quit;
-
+
case ARG_VERSION:
printf("pactl "PACKAGE_VERSION"\nCompiled with libpulse %s\nLinked with libpulse %s\n", pa_get_headers_version(), pa_get_library_version());
ret = 0;
if (!client_name)
client_name = pa_xstrdup(bn);
-
+
if (optind < argc) {
if (!strcmp(argv[optind], "stat"))
action = STAT;
tmp[n] = 0;
sample_name = pa_xstrdup(tmp);
}
-
+
memset(&sfinfo, 0, sizeof(sfinfo));
if (!(sndfile = sf_open(argv[optind+1], SFM_READ, &sfinfo))) {
fprintf(stderr, "Failed to open sound file.\n");
goto quit;
}
-
+
sample_spec.format = PA_SAMPLE_FLOAT32;
sample_spec.rate = sfinfo.samplerate;
sample_spec.channels = sfinfo.channels;
if (optind+2 < argc)
device = pa_xstrdup(argv[optind+2]);
-
+
} else if (!strcmp(argv[optind], "remove-sample")) {
action = REMOVE_SAMPLE;
if (optind+1 >= argc) {
#ifdef SIGPIPE
signal(SIGPIPE, SIG_IGN);
#endif
-
+
if (!(context = pa_context_new(mainloop_api, client_name))) {
fprintf(stderr, "pa_context_new() failed.\n");
goto quit;
pa_signal_done();
pa_mainloop_free(m);
}
-
+
if (sndfile)
sf_close(sndfile);
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
pthread_mutex_t mutex;
int ref;
int unusable;
-
+
fd_info_type_t type;
int app_fd, thread_fd;
int volume_modify_count;
int optr_n_blocks;
-
+
PA_LLIST_FIELDS(fd_info);
};
* -> disable /dev/dsp emulation, bit 2 -> disable /dev/sndstat
* emulation, bit 3 -> disable /dev/mixer emulation. Hence a value
* of 7 disables padsp entirely. */
-
+
pthread_mutex_lock(&func_mutex);
if (!sym_resolved) {
sym = (int*) dlsym(RTLD_DEFAULT, "__padsp_disabled__");
if (!sym)
return 0;
-
+
return *sym;
}
static int dsp_cloak_enable(void) {
if (padsp_disabled() & 1)
return 0;
-
+
if (getenv("PADSP_NO_DSP"))
return 0;
/* Avoid recursive calls */
static pthread_once_t recursion_key_once = PTHREAD_ONCE_INIT;
pthread_once(&recursion_key_once, recursion_key_alloc);
-
+
if (pthread_getspecific(recursion_key))
return 0;
debug(DEBUG_LEVEL_NORMAL, __FILE__": freeing fd info (fd=%i)\n", i->app_fd);
dsp_drain(i);
-
+
if (i->mainloop)
pa_threaded_mainloop_stop(i->mainloop);
-
+
if (i->play_stream) {
pa_stream_disconnect(i->play_stream);
pa_stream_unref(i->play_stream);
pa_context_disconnect(i->context);
pa_context_unref(i->context);
}
-
+
if (i->mainloop)
pa_threaded_mainloop_free(i->mainloop);
static fd_info *fd_info_ref(fd_info *i) {
assert(i);
-
+
pthread_mutex_lock(&i->mutex);
assert(i->ref >= 1);
i->ref++;
static void reset_params(fd_info *i) {
assert(i);
-
+
i->sample_spec.format = PA_SAMPLE_U8;
i->sample_spec.channels = 1;
i->sample_spec.rate = 8000;
if ((e = getenv("PADSP_CLIENT_NAME")))
return e;
-
+
if (pa_get_binary_name(p, sizeof(p)))
snprintf(buf, n, "OSS Emulation[%s]", p);
else
fd_info *i;
debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_prepare() enter\n");
-
+
function_enter();
pthread_mutex_lock(&fd_infos_mutex);
pthread_mutex_lock(&func_mutex);
-
+
debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_prepare() exit\n");
}
static void atfork_parent(void) {
fd_info *i;
-
+
debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_parent() enter\n");
pthread_mutex_unlock(&func_mutex);
pthread_mutex_unlock(&fd_infos_mutex);
function_exit();
-
+
debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_parent() exit\n");
}
static void atfork_child(void) {
fd_info *i;
-
+
debug(DEBUG_LEVEL_NORMAL, __FILE__": atfork_child() enter\n");
/* We do only the bare minimum to get all fds closed */
pthread_mutex_init(&func_mutex, NULL);
pthread_mutex_init(&fd_infos_mutex, NULL);
-
+
for (i = fd_infos; i; i = i->next) {
pthread_mutex_init(&i->mutex, NULL);
signal(SIGPIPE, SIG_IGN); /* Yes, ugly as hell */
pthread_once(&install_atfork_once, install_atfork);
-
+
if (!(i = malloc(sizeof(fd_info)))) {
*_errno = ENOMEM;
goto fail;
unlock_and_fail:
pa_threaded_mainloop_unlock(i->mainloop);
-
+
fail:
if (i)
fd_info_unref(i);
-
+
return NULL;
}
fd_info *i;
pthread_mutex_lock(&fd_infos_mutex);
-
+
for (i = fd_infos; i; i = i->next)
if (i->app_fd == fd && !i->unusable) {
fd_info_ref(i);
}
pthread_mutex_unlock(&fd_infos_mutex);
-
+
return i;
}
case PA_STREAM_READY:
debug(DEBUG_LEVEL_NORMAL, __FILE__": stream established.\n");
break;
-
+
case PA_STREAM_FAILED:
debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context)));
fd_info_shutdown(i);
static int create_playback_stream(fd_info *i) {
pa_buffer_attr attr;
int n;
-
+
assert(i);
fix_metrics(i);
attr.tlength = i->fragment_size * i->n_fragments;
attr.prebuf = i->fragment_size;
attr.minreq = i->fragment_size;
-
+
if (pa_stream_connect_playback(i->play_stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL) < 0) {
debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context)));
goto fail;
setsockopt(i->app_fd, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n));
n = i->fragment_size;
setsockopt(i->thread_fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n));
-
+
return 0;
fail:
static int create_record_stream(fd_info *i) {
pa_buffer_attr attr;
int n;
-
+
assert(i);
fix_metrics(i);
memset(&attr, 0, sizeof(attr));
attr.maxlength = i->fragment_size * (i->n_fragments+1);
attr.fragsize = i->fragment_size;
-
+
if (pa_stream_connect_record(i->rec_stream, NULL, &attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE) < 0) {
debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_connect_playback() failed: %s\n", pa_strerror(pa_context_errno(i->context)));
goto fail;
setsockopt(i->app_fd, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n));
n = i->fragment_size;
setsockopt(i->thread_fd, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n));
-
+
return 0;
fail:
fd_info *i = userdata;
pa_threaded_mainloop_signal(i->mainloop, 0);
-
+
if (flags & PA_IO_EVENT_INPUT) {
if (!i->play_stream) {
if (fd_info_copy_data(i, 0) < 0)
goto fail;
}
-
+
} else if (flags & PA_IO_EVENT_OUTPUT) {
if (!i->rec_stream) {
goto fail;
return;
-
+
fail:
/* We can't do anything better than removing the event source */
fd_info_shutdown(i);
if (!(i->io_event = api->io_new(api, i->thread_fd, i->io_flags, io_event_cb, i)))
goto fail;
-
+
pa_threaded_mainloop_unlock(i->mainloop);
debug(DEBUG_LEVEL_NORMAL, __FILE__": dsp_open() succeeded, fd=%i\n", i->app_fd);
fd_info_add_to_list(i);
ret = i->app_fd;
fd_info_unref(i);
-
+
return ret;
fail:
if (i)
fd_info_unref(i);
-
+
*_errno = EIO;
debug(DEBUG_LEVEL_NORMAL, __FILE__": dsp_open() failed\n");
if (!pa_cvolume_equal(&i->sink_volume, &si->volume))
i->volume_modify_count++;
-
+
i->sink_volume = si->volume;
i->sink_index = si->index;
if (!pa_cvolume_equal(&i->source_volume, &si->volume))
i->volume_modify_count++;
-
+
i->source_volume = si->volume;
i->source_index = si->index;
debug(DEBUG_LEVEL_NORMAL, __FILE__": mixer_open()\n");
- if (!(i = fd_info_new(FD_INFO_MIXER, _errno)))
+ if (!(i = fd_info_new(FD_INFO_MIXER, _errno)))
return -1;
-
+
pa_threaded_mainloop_lock(i->mainloop);
pa_context_set_subscribe_callback(i->context, subscribe_cb, i);
-
+
if (!(o = pa_context_subscribe(i->context, PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE, context_success_cb, i))) {
debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to subscribe to events: %s", pa_strerror(pa_context_errno(i->context)));
*_errno = EIO;
fd_info_add_to_list(i);
ret = i->app_fd;
fd_info_unref(i);
-
+
return ret;
fail:
if (i)
fd_info_unref(i);
-
+
*_errno = EIO;
debug(DEBUG_LEVEL_NORMAL, __FILE__": mixer_open() failed\n");
int e;
debug(DEBUG_LEVEL_NORMAL, __FILE__": sndstat_open()\n");
-
+
if (flags != O_RDONLY
#ifdef O_LARGEFILE
&& flags != (O_RDONLY|O_LARGEFILE)
}
function_exit();
-
+
if (_errno)
errno = _errno;
-
+
return r;
}
static int mixer_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) {
int ret = -1;
-
+
switch (request) {
case SOUND_MIXER_READ_DEVMASK :
debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_DEVMASK\n");
*(int*) argp = SOUND_MASK_IGAIN;
break;
-
+
case SOUND_MIXER_READ_STEREODEVS:
debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_MIXER_READ_STEREODEVS\n");
if (i->source_volume.channels > 1)
*(int*) argp |= SOUND_MASK_IGAIN;
pa_threaded_mainloop_unlock(i->mainloop);
-
+
break;
case SOUND_MIXER_READ_RECSRC:
*(int*) argp = 0;
break;
-
+
case SOUND_MIXER_READ_PCM:
case SOUND_MIXER_READ_IGAIN: {
pa_cvolume *v;
i->operation_success = 0;
while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
CONTEXT_CHECK_DEAD_GOTO(i, exit_loop);
-
+
pa_threaded_mainloop_wait(i->mainloop);
}
exit_loop:
-
+
if (!i->operation_success)
debug(DEBUG_LEVEL_NORMAL, __FILE__": Failed to set volume: %s\n", pa_strerror(pa_context_errno(i->context)));
pa_operation_unref(o);
}
-
+
/* We don't wait for completion here */
i->volume_modify_count++;
}
-
+
pa_threaded_mainloop_unlock(i->mainloop);
-
+
break;
}
pa_threaded_mainloop_unlock(i->mainloop);
break;
}
-
+
default:
debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request);
}
ret = 0;
-
+
fail:
-
+
return ret;
}
static int map_format(int *fmt, pa_sample_spec *ss) {
-
+
switch (*fmt) {
case AFMT_MU_LAW:
ss->format = PA_SAMPLE_ULAW;
break;
-
+
case AFMT_A_LAW:
ss->format = PA_SAMPLE_ALAW;
break;
-
+
case AFMT_S8:
*fmt = AFMT_U8;
/* fall through */
case AFMT_U8:
ss->format = PA_SAMPLE_U8;
break;
-
+
case AFMT_U16_BE:
*fmt = AFMT_S16_BE;
/* fall through */
case AFMT_S16_BE:
ss->format = PA_SAMPLE_S16BE;
break;
-
+
case AFMT_U16_LE:
*fmt = AFMT_S16_LE;
/* fall through */
case AFMT_S16_LE:
ss->format = PA_SAMPLE_S16LE;
break;
-
+
default:
ss->format = PA_SAMPLE_S16NE;
*fmt = AFMT_S16_NE;
static int dsp_empty_socket(fd_info *i) {
#ifdef SIOCINQ
int ret = -1;
-
+
/* Empty the socket */
for (;;) {
int l;
-
+
if (i->thread_fd < 0)
break;
-
+
if (ioctl(i->thread_fd, SIOCINQ, &l) < 0) {
debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ: %s\n", strerror(errno));
break;
ret = 0;
break;
}
-
+
pa_threaded_mainloop_wait(i->mainloop);
}
if (!i->mainloop)
return 0;
-
+
debug(DEBUG_LEVEL_NORMAL, __FILE__": Draining.\n");
pa_threaded_mainloop_lock(i->mainloop);
if (dsp_empty_socket(i) < 0)
goto fail;
-
+
if (!i->play_stream)
goto fail;
debug(DEBUG_LEVEL_NORMAL, __FILE__": Really draining.\n");
-
+
if (!(o = pa_stream_drain(i->play_stream, stream_success_cb, i))) {
debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_drain(): %s\n", pa_strerror(pa_context_errno(i->context)));
goto fail;
i->operation_success = 0;
while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, fail);
-
+
pa_threaded_mainloop_wait(i->mainloop);
}
}
r = 0;
-
+
fail:
-
+
if (o)
pa_operation_unref(o);
goto fail;
debug(DEBUG_LEVEL_NORMAL, __FILE__": Triggering.\n");
-
+
if (!(o = pa_stream_trigger(i->play_stream, stream_success_cb, i))) {
debug(DEBUG_LEVEL_NORMAL, __FILE__": pa_stream_trigger(): %s\n", pa_strerror(pa_context_errno(i->context)));
goto fail;
i->operation_success = 0;
while (!pa_operation_get_state(o) != PA_OPERATION_DONE) {
PLAYBACK_STREAM_CHECK_DEAD_GOTO(i, fail);
-
+
pa_threaded_mainloop_wait(i->mainloop);
}
}
r = 0;
-
+
fail:
-
+
if (o)
pa_operation_unref(o);
static int dsp_ioctl(fd_info *i, unsigned long request, void*argp, int *_errno) {
int ret = -1;
-
+
switch (request) {
case SNDCTL_DSP_SETFMT: {
debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETFMT: %i\n", *(int*) argp);
-
+
pa_threaded_mainloop_lock(i->mainloop);
if (*(int*) argp == AFMT_QUERY)
pa_threaded_mainloop_unlock(i->mainloop);
break;
}
-
+
case SNDCTL_DSP_SPEED: {
pa_sample_spec ss;
int valid;
char t[256];
-
+
debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SPEED: %i\n", *(int*) argp);
pa_threaded_mainloop_lock(i->mainloop);
i->sample_spec = ss;
free_streams(i);
}
-
+
debug(DEBUG_LEVEL_NORMAL, __FILE__": ss: %s\n", pa_sample_spec_snprint(t, sizeof(t), &i->sample_spec));
pa_threaded_mainloop_unlock(i->mainloop);
break;
}
-
+
case SNDCTL_DSP_STEREO:
debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_STEREO: %i\n", *(int*) argp);
-
+
pa_threaded_mainloop_lock(i->mainloop);
-
+
i->sample_spec.channels = *(int*) argp ? 2 : 1;
free_streams(i);
-
+
pa_threaded_mainloop_unlock(i->mainloop);
return 0;
case SNDCTL_DSP_CHANNELS: {
pa_sample_spec ss;
int valid;
-
+
debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_CHANNELS: %i\n", *(int*) argp);
-
+
pa_threaded_mainloop_lock(i->mainloop);
ss = i->sample_spec;
i->sample_spec = ss;
free_streams(i);
}
-
+
pa_threaded_mainloop_unlock(i->mainloop);
if (!valid) {
fix_metrics(i);
*(int*) argp = i->fragment_size;
-
+
pa_threaded_mainloop_unlock(i->mainloop);
-
+
break;
case SNDCTL_DSP_SETFRAGMENT:
debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SETFRAGMENT: 0x%08x\n", *(int*) argp);
-
+
pa_threaded_mainloop_lock(i->mainloop);
-
+
i->fragment_size = 1 << ((*(int*) argp) & 31);
i->n_fragments = (*(int*) argp) >> 16;
i->n_fragments = 12;
free_streams(i);
-
+
pa_threaded_mainloop_unlock(i->mainloop);
-
+
break;
-
+
case SNDCTL_DSP_GETCAPS:
debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_CAPS\n");
-
+
*(int*) argp = DSP_CAP_DUPLEX
#ifdef DSP_CAP_MULTI
| DSP_CAP_MULTI
case SNDCTL_DSP_GETODELAY: {
int l;
-
+
debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETODELAY\n");
-
+
pa_threaded_mainloop_lock(i->mainloop);
*(int*) argp = 0;
-
+
for (;;) {
pa_usec_t usec;
pa_threaded_mainloop_wait(i->mainloop);
}
-
+
exit_loop:
-#ifdef SIOCINQ
+#ifdef SIOCINQ
if (ioctl(i->thread_fd, SIOCINQ, &l) < 0)
debug(DEBUG_LEVEL_NORMAL, __FILE__": SIOCINQ failed: %s\n", strerror(errno));
else
break;
}
-
+
case SNDCTL_DSP_RESET: {
debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_RESET\n");
-
+
pa_threaded_mainloop_lock(i->mainloop);
free_streams(i);
dsp_flush_socket(i);
i->optr_n_blocks = 0;
-
+
pa_threaded_mainloop_unlock(i->mainloop);
break;
}
-
+
case SNDCTL_DSP_GETFMTS: {
debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETFMTS\n");
-
+
*(int*) argp = AFMT_MU_LAW|AFMT_A_LAW|AFMT_U8|AFMT_S16_LE|AFMT_S16_BE;
break;
}
case SNDCTL_DSP_POST:
debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_POST\n");
-
- if (dsp_trigger(i) < 0)
+
+ if (dsp_trigger(i) < 0)
*_errno = EIO;
break;
- case SNDCTL_DSP_SYNC:
+ case SNDCTL_DSP_SYNC:
debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_SYNC\n");
-
- if (dsp_drain(i) < 0)
+
+ if (dsp_drain(i) < 0)
*_errno = EIO;
break;
case SOUND_PCM_READ_RATE:
debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_PCM_READ_RATE\n");
-
+
pa_threaded_mainloop_lock(i->mainloop);
*(int*) argp = i->sample_spec.rate;
pa_threaded_mainloop_unlock(i->mainloop);
- break;
+ break;
case SOUND_PCM_READ_CHANNELS:
debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_PCM_READ_CHANNELS\n");
-
+
pa_threaded_mainloop_lock(i->mainloop);
*(int*) argp = i->sample_spec.channels;
pa_threaded_mainloop_unlock(i->mainloop);
- break;
+ break;
case SOUND_PCM_READ_BITS:
debug(DEBUG_LEVEL_NORMAL, __FILE__": SOUND_PCM_READ_BITS\n");
-
+
pa_threaded_mainloop_lock(i->mainloop);
*(int*) argp = pa_sample_size(&i->sample_spec)*8;
pa_threaded_mainloop_unlock(i->mainloop);
- break;
-
+ break;
+
case SNDCTL_DSP_GETOPTR: {
count_info *info;
-
+
debug(DEBUG_LEVEL_NORMAL, __FILE__": SNDCTL_DSP_GETOPTR\n");
info = (count_info*) argp;
memset(info, 0, sizeof(*info));
-
+
pa_threaded_mainloop_lock(i->mainloop);
for (;;) {
if (pa_stream_get_time(i->play_stream, &usec) >= 0) {
size_t k = pa_usec_to_bytes(usec, &i->sample_spec);
int m;
-
+
info->bytes = (int) k;
m = k / i->fragment_size;
info->blocks = m - i->optr_n_blocks;
pa_threaded_mainloop_wait(i->mainloop);
}
-
+
pa_threaded_mainloop_unlock(i->mainloop);
debug(DEBUG_LEVEL_NORMAL, __FILE__": GETOPTR bytes=%i, blocks=%i, ptr=%i\n", info->bytes, info->blocks, info->ptr);
case SNDCTL_DSP_GETIPTR:
debug(DEBUG_LEVEL_NORMAL, __FILE__": invalid ioctl SNDCTL_DSP_GETIPTR\n");
goto inval;
-
+
default:
debug(DEBUG_LEVEL_NORMAL, __FILE__": unknown ioctl 0x%08lx\n", request);
}
ret = 0;
-
+
fail:
-
+
return ret;
}
r = mixer_ioctl(i, request, argp, &_errno);
else
r = dsp_ioctl(i, request, argp, &_errno);
-
+
fd_info_unref(i);
if (_errno)
errno = _errno;
function_exit();
-
+
return r;
}
fd_info_remove_from_list(i);
fd_info_unref(i);
-
+
function_exit();
return 0;
errno = EFAULT;
return -1;
}
-
+
debug(DEBUG_LEVEL_VERBOSE, __FILE__": access(%s)\n", pathname);
if (strcmp(pathname, "/dev/dsp") != 0 &&
mode_t mode = 0;
debug(DEBUG_LEVEL_VERBOSE, __FILE__": open64(%s)\n", filename);
-
+
va_start(args, flags);
if (flags & O_CREAT)
mode = va_arg(args, mode_t);
FILE *f = NULL;
int fd;
mode_t m;
-
+
debug(DEBUG_LEVEL_VERBOSE, __FILE__": fopen(%s)\n", filename);
if (strcmp(filename, "/dev/dsp") != 0 &&
close(fd);
return NULL;
}
-
+
return f;
}
/* Dirty trick to avoid that the fd is not freed twice, once by us
* and once by the real fclose() */
i->app_fd = -1;
-
+
fd_info_unref(i);
-
+
function_exit();
LOAD_FCLOSE_FUNC();
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
fprintf(stderr, "Failed to drain stream: %s\n", pa_strerror(pa_context_errno(context)));
quit(1);
}
-
- if (verbose)
+
+ if (verbose)
fprintf(stderr, "Playback stream drained.\n");
pa_stream_disconnect(stream);
pa_stream_unref(stream);
stream = NULL;
-
+
if (!(o = pa_context_drain(context, context_drain_complete, NULL)))
pa_context_disconnect(context);
else {
if ((bytes = readf_function(sndfile, data, length/k)) > 0)
bytes *= k;
-
+
} else
bytes = sf_read_raw(sndfile, data, length);
if (verbose)
fprintf(stderr, "Stream successfully created\n");
break;
-
+
case PA_STREAM_FAILED:
default:
fprintf(stderr, "Stream errror: %s\n", pa_strerror(pa_context_errno(pa_stream_get_context(s))));
case PA_CONTEXT_AUTHORIZING:
case PA_CONTEXT_SETTING_NAME:
break;
-
+
case PA_CONTEXT_READY: {
pa_cvolume cv;
-
+
assert(c && !stream);
if (verbose)
pa_stream_set_state_callback(stream, stream_state_callback, NULL);
pa_stream_set_write_callback(stream, stream_write_callback, NULL);
pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, sample_spec.channels, volume), NULL);
-
+
break;
}
-
+
case PA_CONTEXT_TERMINATED:
quit(0);
break;
if (verbose)
fprintf(stderr, "Got SIGINT, exiting.\n");
quit(0);
-
+
}
static void help(const char *argv0) {
help(bn);
ret = 0;
goto quit;
-
+
case ARG_VERSION:
printf("paplay "PACKAGE_VERSION"\nCompiled with libpulse %s\nLinked with libpulse %s\n", pa_get_headers_version(), pa_get_library_version());
ret = 0;
}
filename = optind < argc ? argv[optind] : "STDIN";
-
+
memset(&sfinfo, 0, sizeof(sfinfo));
if (optind < argc)
sample_spec.rate = sfinfo.samplerate;
sample_spec.channels = sfinfo.channels;
-
+
readf_function = NULL;
-
+
switch (sfinfo.format & 0xFF) {
case SF_FORMAT_PCM_16:
case SF_FORMAT_PCM_U8:
sample_spec.format = PA_SAMPLE_S16NE;
readf_function = (sf_count_t (*)(SNDFILE *_sndfile, void *ptr, sf_count_t frames)) sf_readf_short;
break;
-
+
case SF_FORMAT_ULAW:
sample_spec.format = PA_SAMPLE_ULAW;
break;
-
+
case SF_FORMAT_ALAW:
sample_spec.format = PA_SAMPLE_ALAW;
break;
if (!stream_name)
stream_name = pa_utf8_filter(n);
}
-
+
if (verbose) {
char t[PA_SAMPLE_SPEC_SNPRINT_MAX];
pa_sample_spec_snprint(t, sizeof(t), &sample_spec);
fprintf(stderr, "Using sample spec '%s'\n", t);
}
-
+
/* Set up a new main loop */
if (!(m = pa_mainloop_new())) {
fprintf(stderr, "pa_mainloop_new() failed.\n");
#ifdef SIGPIPE
signal(SIGPIPE, SIG_IGN);
#endif
-
+
/* Create a new connection context */
if (!(context = pa_context_new(mainloop_api, client_name))) {
fprintf(stderr, "pa_context_new() failed.\n");
fprintf(stderr, "pa_mainloop_run() failed.\n");
goto quit;
}
-
+
quit:
if (stream)
pa_stream_unref(stream);
if (sndfile)
sf_close(sndfile);
-
+
return ret;
}
/***
This file is part of PulseAudio.
-
+
PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
-
+
PulseAudio is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with PulseAudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
switch (mode) {
case DUMP: {
char t[1024];
- if (pa_x11_get_prop(d, "PULSE_SERVER", t, sizeof(t)))
+ if (pa_x11_get_prop(d, "PULSE_SERVER", t, sizeof(t)))
printf("Server: %s\n", t);
if (pa_x11_get_prop(d, "PULSE_SOURCE", t, sizeof(t)))
printf("Source: %s\n", t);
break;
}
-
+
case IMPORT: {
char t[1024];
- if (pa_x11_get_prop(d, "PULSE_SERVER", t, sizeof(t)))
+ if (pa_x11_get_prop(d, "PULSE_SERVER", t, sizeof(t)))
printf("PULSE_SERVER='%s'\nexport PULSE_SERVER\n", t);
if (pa_x11_get_prop(d, "PULSE_SOURCE", t, sizeof(t)))
printf("PULSE_SOURCE='%s'\nexport PULSE_SOURCE\n", t);
pa_x11_del_prop(d, "PULSE_SOURCE");
pa_x11_del_prop(d, "PULSE_ID");
pa_x11_del_prop(d, "PULSE_COOKIE");
-
+
if (server)
pa_x11_set_prop(d, "PULSE_SERVER", server);
else if (conf->default_server)
fprintf(stderr, "Failed to get FQDN.\n");
goto finish;
}
-
+
pa_x11_set_prop(d, "PULSE_SERVER", hn);
}
pa_x11_set_prop(d, "PULSE_SOURCE", conf->default_source);
pa_client_conf_free(conf);
-
+
if (pa_authkey_load_auto(cookie_file, cookie, sizeof(cookie)) < 0) {
fprintf(stderr, "Failed to load cookie data\n");
goto finish;
pa_x11_del_prop(d, "PULSE_ID");
pa_x11_del_prop(d, "PULSE_COOKIE");
break;
-
+
default:
fprintf(stderr, "No yet implemented.\n");
goto finish;
}
ret = 0;
-
+
finish:
if (d) {
XSync(d, False);
XCloseDisplay(d);
}
-
+
return ret;
}