- cleanup tagstruct (add s32, pa_volume_t, pa_usec_t)
- xmlrpc
- remove all gcc warnings
+- esd compatible startup script or personality
** later ***
- slp/rendezvous
# USA.
AM_CFLAGS=-D_GNU_SOURCE -I$(top_srcdir) $(PTHREAD_CFLAGS)
-AM_CFLAGS+= -DDLSEARCHDIR=\"$(pkglibdir)\"
+#AM_CFLAGS+= -DDLSEARCHDIR=\"$(pkglibdir)\"
AM_LDADD=$(PTHREAD_LIBS)
AM_LIBADD=$(PTHREAD_LIBS)
endif
+
+suid: polypaudio
+ chown root:root $<
+ chmod u+s $<
e = argv0;
printf("%s [options]\n"
+ " -r Try to set high process priority (only available as root)\n"
+ " -R Don't drop root if SETUID root\n"
" -L MODULE Load the specified plugin module with the specified argument\n"
" -F FILE Run the specified script\n"
" -C Open a command line on the running TTY\n"
" -D Daemonize after loading the modules\n"
" -f Dont quit when the startup fails\n"
" -v Verbose startup\n"
- " -h Show this help\n", e);
+ " -h Show this help\n"
+ " -V Show version\n", e);
}
struct pa_cmdline* pa_cmdline_parse(int argc, char * const argv []) {
assert(argc && argv);
cmdline = pa_xmalloc(sizeof(struct pa_cmdline));
- cmdline->daemonize = cmdline->help = cmdline->verbose = 0;
+ cmdline->daemonize = cmdline->help = cmdline->verbose = cmdline->high_priority = cmdline->stay_root = cmdline->version = 0;
cmdline->fail = 1;
buf = pa_strbuf_new();
assert(buf);
- while ((c = getopt(argc, argv, "L:F:CDhfv")) != -1) {
+ while ((c = getopt(argc, argv, "L:F:CDhfvrRV")) != -1) {
switch (c) {
case 'L':
pa_strbuf_printf(buf, "load %s\n", optarg);
cmdline->fail = 0;
break;
case 'v':
- cmdline->verbose = 0;
+ cmdline->verbose = 1;
break;
+ case 'r':
+ cmdline->high_priority = 1;
+ break;
+ case 'R':
+ cmdline->stay_root = 1;
+ break;
+ case 'V':
+ cmdline->version = 1;
+ break;
+
default:
goto fail;
}
struct pa_cmdline {
- int daemonize, help, fail, verbose;
+ int daemonize, help, fail, verbose, high_priority, stay_root, version;
char *cli_commands;
};
ssize_t pa_iochannel_write(struct pa_iochannel*io, const void*data, size_t l) {
ssize_t r;
+ assert(io);
+ assert(data);
+ assert(l);
+ assert(io->ofd >= 0);
+
+
assert(io && data && l && io->ofd >= 0);
+
+
if ((r = write(io->ofd, data, l)) >= 0) {
io->writable = 0;
enable_mainloop_sources(io);
static struct pa_mainloop *mainloop;
+static void drop_root(void) {
+ if (getuid() != 0 && geteuid() == 0) {
+ fprintf(stderr, __FILE__": started SUID root, dropping root rights.\n");
+ setuid(getuid());
+ seteuid(getuid());
+ }
+}
+
static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) {
m->quit(m, 1);
fprintf(stderr, __FILE__": got signal.\n");
goto finish;
}
+ if (cmdline->version) {
+ printf(PACKAGE_NAME" "PACKAGE_VERSION"\n");
+ retval = 0;
+ goto finish;
+ }
+
+ if (cmdline->high_priority)
+ pa_raise_priority();
+
+ if (!cmdline->stay_root)
+ drop_root();
+
if (cmdline->daemonize) {
pid_t child;
static void scan_dead(struct pa_mainloop *m) {
int all = 0;
assert(m);
+
if (m->io_events_scan_dead)
pa_idxset_foreach(m->io_events, io_foreach, &all);
if (m->time_events_scan_dead)
for (e = pa_idxset_first(m->defer_events, &index); e; e = pa_idxset_next(m->defer_events, &index)) {
if (e->dead || !e->enabled)
continue;
-
+
assert(e->callback);
e->callback(&m->api, e, e->userdata);
}
struct pa_time_event *e;
struct timeval now;
int t = -1;
+ int got_time = 0;
if (pa_idxset_isempty(m->time_events))
return -1;
- gettimeofday(&now, NULL);
-
for (e = pa_idxset_first(m->time_events, &index); e; e = pa_idxset_next(m->time_events, &index)) {
int tmp;
if (e->dead || !e->enabled)
continue;
+ /* Let's save a system call */
+ if (!got_time) {
+ gettimeofday(&now, NULL);
+ got_time = 1;
+ }
+
if (e->timeval.tv_sec < now.tv_sec || (e->timeval.tv_sec == now.tv_sec && e->timeval.tv_usec <= now.tv_usec))
return 0;
uint32_t index;
struct pa_time_event *e;
struct timeval now;
+ int got_time = 0;
assert(m);
if (pa_idxset_isempty(m->time_events))
return;
- gettimeofday(&now, NULL);
for (e = pa_idxset_first(m->time_events, &index); e; e = pa_idxset_next(m->time_events, &index)) {
if (e->dead || !e->enabled)
continue;
+ /* Let's save a system call */
+ if (!got_time) {
+ gettimeofday(&now, NULL);
+ got_time = 1;
+ }
+
if (e->timeval.tv_sec < now.tv_sec || (e->timeval.tv_sec == now.tv_sec && e->timeval.tv_usec <= now.tv_usec)) {
assert(e->callback);
bq->current_length = 0;
- fprintf(stderr, "memblockq requested: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u\n", maxlength, tlength, base, prebuf, minreq);
+ /*fprintf(stderr, "memblockq requested: maxlength=%u, tlength=%u, base=%u, prebuf=%u, minreq=%u\n", maxlength, tlength, base, prebuf, minreq);*/
bq->base = base;
bq->n_blocks = 0;
bq->current_length = 0;
}
+
+uint32_t pa_memblockq_get_tlength(struct pa_memblockq *bq) {
+ assert(bq);
+ return bq->tlength;
+}
/* Flush the queue */
void pa_memblockq_flush(struct pa_memblockq *bq);
+/* Get Target length */
+uint32_t pa_memblockq_get_tlength(struct pa_memblockq *bq);
+
#endif
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, memchunk->memblock->data + memchunk->index, 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 == -EAGAIN)
return;
assert(u->memchunk.memblock && u->memchunk.memblock->data && u->memchunk.length && u->memchunk.memblock->length && (u->memchunk.length % u->frame_size) == 0);
- if ((frames = snd_pcm_readi(u->pcm_handle, u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length / u->frame_size)) < 0) {
+ 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;
return;
update_usage(u);
-
- if (!u->memchunk.length) {
- if (pa_sink_render(u->sink, u->out_fragment_size, &u->memchunk) < 0)
- memchunk = &u->silence;
- else
- memchunk = &u->memchunk;
- }
- assert(memchunk->memblock && memchunk->length);
+ memchunk = &u->memchunk;
+
+ if (!memchunk->length)
+ if (pa_sink_render(u->sink, u->out_fragment_size, memchunk) < 0)
+ memchunk = &u->silence;
- if ((r = pa_iochannel_write(u->io, memchunk->memblock->data + memchunk->index, memchunk->length)) < 0) {
+ 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) {
fprintf(stderr, "write() failed: %s\n", strerror(errno));
return;
}
-
+
if (memchunk == &u->silence)
assert(r % u->sample_size == 0);
else {
fprintf(stderr, "module-oss: device opened in %s mode.\n", mode == O_WRONLY ? "O_WRONLY" : (mode == O_RDONLY ? "O_RDONLY" : "O_RDWR"));
- 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;
assert(u->memchunk.memblock && u->memchunk.length);
- if ((r = pa_iochannel_write(u->io, u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) {
+ if ((r = pa_iochannel_write(u->io, (uint8_t*) u->memchunk.memblock->data + u->memchunk.index, u->memchunk.length)) < 0) {
fprintf(stderr, "write() failed: %s\n", strerror(errno));
return;
}
-#!./polypaudio -F
+#!./polypaudio -rF
#
# This file is part of polypaudio.
#load module-alsa-source device=plughw:1,0
#load module-oss device="/dev/dsp" sink_name=output source_name=input
#load module-oss-mmap device="/dev/dsp" sink_name=output source_name=input
-load module-pipe-sink
+#load module-pipe-sink
# Load audio drivers automatically on access
-#autoload_sink_add output module-oss device="/dev/dsp" sink_name=output source_name=input
-#autoload_source_add input module-oss device="/dev/dsp" sink_name=output source_name=input
+autoload_sink_add output module-oss device="/dev/adsp" sink_name=output source_name=input
+autoload_source_add input module-oss device="/dev/adsp" sink_name=output source_name=input
#autoload_sink_add output module-oss-mmap device="/dev/dsp" sink_name=output source_name=input
#autoload_source_add input module-oss-mmap device="/dev/dsp" sink_name=output source_name=input
-autoload_sink_add output module-alsa-sink sink_name=output
-autoload_source_add input module-alsa-source source_name=input
+#autoload_sink_add output module-alsa-sink sink_name=output
+#autoload_source_add input module-alsa-source source_name=input
# Load several protocols
-load module-esound-protocol-tcp
-load module-simple-protocol-tcp
+#load module-esound-protocol-tcp
+#load module-simple-protocol-tcp
load module-native-protocol-unix
-load module-cli-protocol-unix
+#load module-cli-protocol-unix
+load module-esound-protocol-unix
# Load the CLI module
load module-cli
if ((s = pa_dynarray_get(c->record_streams, channel))) {
if (s->read_callback)
- s->read_callback(s, chunk->memblock->data + chunk->index, chunk->length, s->read_userdata);
+ s->read_callback(s, (uint8_t*) chunk->memblock->data + chunk->index, chunk->length, s->read_userdata);
}
pa_context_unref(c);
else {
if (o->callback) {
void (*cb)(struct pa_context *c, void *userdata);
- cb = (void*) o->callback;
+ cb = (void (*)(struct pa_context*, void*)) o->callback;
cb(o->context, o->userdata);
}
#include "llist.h"
#include "native-common.h"
-#define DEFAULT_TLENGTH (10240*2)
-#define DEFAULT_MAXLENGTH (DEFAULT_TLENGTH*2)
+#define DEFAULT_TLENGTH (10240*4)
+#define DEFAULT_MAXLENGTH ((DEFAULT_TLENGTH*3)/2)
#define DEFAULT_PREBUF DEFAULT_TLENGTH
-#define DEFAULT_MINREQ 1024
+#define DEFAULT_MINREQ 512
#define DEFAULT_FRAGSIZE 1024
#define DEFAULT_TIMEOUT (5*60)
/* do something */
assert(c->protocol && c->protocol->core && c->protocol->core->mainloop && c->protocol->core->mainloop->defer_enable);
c->protocol->core->mainloop->defer_enable(c->defer_event, 1);
+
+ assert(pa_memblockq_get_length(c->input_memblockq) > 2048);
}
static void sink_input_kill_cb(struct pa_sink_input *i) {
assert(i && i->userdata && chunk);
s = i->userdata;
+ /*fprintf(stderr, "%3.0f \r", (double) pa_memblockq_get_length(s->memblockq)/pa_memblockq_get_tlength(s->memblockq)*100);*/
+
if (pa_memblockq_peek(s->memblockq, chunk) < 0)
return -1;
else {
assert(command == PA_COMMAND_FLUSH_PLAYBACK_STREAM);
pa_memblockq_flush(s->memblockq);
+ /*fprintf(stderr, "flush: %u\n", pa_memblockq_get_length(s->memblockq));*/
}
pa_sink_notify(s->sink_input->sink);
l = chunk->length;
if (l > 0) {
- memcpy(u->memchunk.memblock->data + u->memchunk.index + u->memchunk.length, chunk->memblock->data+chunk->index, l);
+ memcpy((uint8_t*) u->memchunk.memblock->data + u->memchunk.index + u->memchunk.length,
+ (uint8_t*) chunk->memblock->data+chunk->index, l);
u->memchunk.length += l;
u->length -= l;
}
assert(p && c);
connection_free(c);
- fprintf(stderr, "protocol-native: connection died.\n");
+/* fprintf(stderr, "protocol-native: connection died.\n");*/
}
p->memblock_stat = s;
+ pa_iochannel_socket_set_rcvbuf(io, 1024*8);
+ pa_iochannel_socket_set_sndbuf(io, 1024*8);
+
return p;
}
if (l > info[0].chunk.length)
l = info[0].chunk.length;
- memcpy(target->memblock->data+target->index, info[0].chunk.memblock->data + info[0].chunk.index, l);
+ memcpy((uint8_t*) target->memblock->data+target->index, (uint8_t*) info[0].chunk.memblock->data + info[0].chunk.index, l);
target->length = l;
if (s->volume != PA_VOLUME_NORM || info[0].volume != PA_VOLUME_NORM)
if (volume != PA_VOLUME_NORM)
pa_volume_memchunk(target, &s->sample_spec, volume);
} else
- target->length = l = pa_mix(info, n, target->memblock->data+target->index, target->length, &s->sample_spec, s->volume);
+ target->length = l = pa_mix(info, n, (uint8_t*) target->memblock->data+target->index, target->length, &s->sample_spec, s->volume);
assert(l);
inputs_drop(s, info, n, l);
}
}
+void pa_sink_render_full(struct pa_sink *s, size_t length, struct pa_memchunk *result) {
+ assert(s && length && result);
+
+ /*** This needs optimization ***/
+
+ result->memblock = pa_memblock_new(result->length = length, s->core->memblock_stat);
+ result->index = 0;
+
+ pa_sink_render_into_full(s, result);
+}
+
pa_usec_t pa_sink_get_latency(struct pa_sink *s) {
assert(s);
void pa_sink_free(struct pa_sink* s);
int pa_sink_render(struct pa_sink*s, size_t length, struct pa_memchunk *result);
+void pa_sink_render_full(struct pa_sink *s, size_t length, struct pa_memchunk *result);
int pa_sink_render_into(struct pa_sink*s, struct pa_memchunk *target);
void pa_sink_render_into_full(struct pa_sink *s, struct pa_memchunk *target);
-
+
pa_usec_t pa_sink_get_latency(struct pa_sink *s);
void pa_sink_notify(struct pa_sink*s);
int pa_socket_set_rcvbuf(int fd, size_t l) {
assert(fd >= 0);
- if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &l, sizeof(l)) < 0)
+ if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &l, sizeof(l)) < 0) {
+ fprintf(stderr, "SO_RCVBUF: %s\n", strerror(errno));
return -1;
+ }
return 0;
}
int pa_socket_set_sndbuf(int fd, size_t l) {
assert(fd >= 0);
- if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &l, sizeof(l)) < 0)
+ if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &l, sizeof(l)) < 0) {
+ fprintf(stderr, "SO_SNDBUF: %s\n", strerror(errno));
return -1;
+ }
return 0;
}
#include <signal.h>
#include <pthread.h>
#include <sys/time.h>
+#include <sched.h>
+#include <sys/resource.h>
#include "util.h"
#include "xmalloc.h"
break;
ret += r;
- data += r;
+ data = (uint8_t*) data + r;
size -= r;
}
break;
ret += r;
- data += r;
+ data = (uint8_t*) data + r;
size -= r;
}
return r;
}
+
+#define NICE_LEVEL (-15)
+
+void pa_raise_priority(void) {
+ if (setpriority(PRIO_PROCESS, 0, NICE_LEVEL) < 0)
+ fprintf(stderr, __FILE__": setpriority() failed: %s\n", strerror(errno));
+ else
+ fprintf(stderr, __FILE__": Successfully gained nice level %i.\n", NICE_LEVEL);
+
+#ifdef _POSIX_PRIORITY_SCHEDULING
+ {
+ struct sched_param sp;
+ sched_getparam(0, &sp);
+ sp.sched_priority = 1;
+ if (sched_setscheduler(0, SCHED_FIFO, &sp) < 0)
+ fprintf(stderr, __FILE__": sched_setscheduler() failed: %s\n", strerror(errno));
+ else
+ fprintf(stderr, __FILE__": Successfully gained SCHED_FIFO scheduling.\n");
+ }
+#endif
+}
+
+void pa_reset_priority(void) {
+#ifdef _POSIX_PRIORITY_SCHEDULING
+ {
+ struct sched_param sp;
+ sched_getparam(0, &sp);
+ sp.sched_priority = 0;
+ sched_setscheduler(0, SCHED_OTHER, &sp);
+ }
+#endif
+
+ setpriority(PRIO_PROCESS, 0, 0);
+}
uint32_t pa_age(struct timeval *tv);
+void pa_raise_priority(void);
+void pa_reset_priority(void);
+
#endif