Mega patch:

* implement inner loops using liboil
* drop "typeid" stuff
* add support for channel maps
* add support for seperate volumes per channel
* add support for hardware mixer settings (only module-oss implements this for now)
* fix a lot of types for _t suffix


git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@463 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
Lennart Poettering 2006-01-27 16:25:31 +00:00
parent 759721cbbc
commit dd10c98241
114 changed files with 2584 additions and 1329 deletions

View file

@ -47,6 +47,7 @@ AM_CFLAGS += $(PTHREAD_CFLAGS) -D_POSIX_PTHREAD_SEMANTICS
AM_CFLAGS += $(LTDLINCL)
AM_CFLAGS += $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS)
AM_CFLAGS += -DDLSEARCHPATH=\"$(modlibdir)\"
#AM_CFLAGS += -DDLSEARCHPATH=\"$(shell pwd)\"
AM_CFLAGS += -DDEFAULT_CONFIG_DIR=\"$(DEFAULT_CONFIG_DIR)\"
AM_CFLAGS += -DPOLYPAUDIO_BINARY=\"$(POLYPAUDIO_BINARY)\"
@ -101,10 +102,10 @@ polypaudio_SOURCES = \
main.c \
pid.c pid.h
polypaudio_CFLAGS = $(AM_CFLAGS)
polypaudio_CPPFLAGS = $(AM_CPPFLAGS)
polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBOIL_CFLAGS)
polypaudio_CPPFLAGS = $(AM_CPPFLAGS)
polypaudio_LDADD = $(AM_LDADD) libpolypcore.la $(LIBLTDL) \
$(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS)
$(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(CAP_LIBS) $(LIBOIL_LIBS)
polypaudio_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS) -dlopen force $(foreach f,$(PREOPEN_LIBS),-dlopen $(f))
if PREOPEN_MODS
@ -219,7 +220,7 @@ strlist_test_CFLAGS = $(AM_CFLAGS)
strlist_test_LDADD = $(AM_LDADD) $(WINSOCK_LIBS)
strlist_test_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
voltest_SOURCES = voltest.c sample.c
voltest_SOURCES = voltest.c sample.c volume.c volume.h sample.h
voltest_CFLAGS = $(AM_CFLAGS)
voltest_LDADD = $(AM_LDADD)
voltest_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
@ -265,8 +266,7 @@ polypinclude_HEADERS = \
polyplib-stream.h \
polyplib-subscribe.h \
polyplib-version.h \
sample.h \
typeid.h
sample.h
if HAVE_HOWL
polypinclude_HEADERS += \
@ -333,10 +333,11 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = \
strbuf.c strbuf.h \
strlist.c strlist.h \
tagstruct.c tagstruct.h \
typeid.c typeid.h \
util.c util.h \
winsock.h \
xmalloc.c xmalloc.h
xmalloc.c xmalloc.h \
channelmap.c channelmap.h \
volume.c volume.h
if HAVE_X11
libpolyp_@PA_MAJORMINOR@_la_SOURCES += \
@ -475,14 +476,15 @@ libpolypcore_la_SOURCES = \
strbuf.c strbuf.h \
subscribe.c subscripe.h \
tokenizer.c tokenizer.h \
typeid.c typeid.h \
util.c util.h \
winsock.h \
xmalloc.c xmalloc.h
xmalloc.c xmalloc.h \
volume.c volume.h \
channelmap.c channelmap.h
libpolypcore_la_CPPFLAGS = $(AM_CPPFLAGS)
libpolypcore_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBOIL_CFLAGS)
libpolypcore_la_LDFLAGS = -avoid-version
libpolypcore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(WINSOCK_LIBS)
libpolypcore_la_LIBADD = $(AM_LIBADD) $(LIBLTDL) $(LIBSAMPLERATE_LIBS) $(LIBSNDFILE_LIBS) $(WINSOCK_LIBS) $(LIBOIL_LIBS)
###################################
# Plug-in support libraries #

View file

@ -85,7 +85,7 @@ finish:
* *io_events. Store the length of that array in *n_io_events. Use the
* specified callback function and userdata. The array has to be freed
* with pa_free_io_events(). */
int pa_create_io_events(snd_pcm_t *pcm_handle, pa_mainloop_api* m, pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags events, void *userdata), void *userdata) {
int pa_create_io_events(snd_pcm_t *pcm_handle, pa_mainloop_api* m, pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata), void *userdata) {
unsigned i;
struct pollfd *pfds, *ppfd;
pa_io_event **ios;

View file

@ -29,7 +29,7 @@
int pa_alsa_set_hw_params(snd_pcm_t *pcm_handle, const pa_sample_spec *ss, uint32_t *periods, snd_pcm_uframes_t *period_size);
int pa_create_io_events(snd_pcm_t *pcm_handle, pa_mainloop_api *m, pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags events, void *userdata), void *userdata);
int pa_create_io_events(snd_pcm_t *pcm_handle, pa_mainloop_api *m, pa_io_event ***io_events, unsigned *n_io_events, void (*cb)(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata), void *userdata);
void pa_free_io_events(pa_mainloop_api* m, pa_io_event **io_sources, unsigned n_io_sources);
#endif

View file

@ -81,7 +81,7 @@ static pa_autoload_entry* entry_new(pa_core *c, const char *name) {
return e;
}
int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type type, const char*module, const char *argument, uint32_t *idx) {
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));
@ -98,7 +98,7 @@ int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type type, const cha
return 0;
}
int pa_autoload_remove_by_name(pa_core *c, const char*name, pa_namereg_type type) {
int pa_autoload_remove_by_name(pa_core *c, const char*name, pa_namereg_type_t type) {
pa_autoload_entry *e;
assert(c && name && type);
@ -120,7 +120,7 @@ int pa_autoload_remove_by_index(pa_core *c, uint32_t idx) {
return 0;
}
void pa_autoload_request(pa_core *c, const char *name, pa_namereg_type type) {
void pa_autoload_request(pa_core *c, const char *name, pa_namereg_type_t type) {
pa_autoload_entry *e;
pa_module *m;
assert(c && name);
@ -159,7 +159,7 @@ void pa_autoload_free(pa_core *c) {
}
}
const pa_autoload_entry* pa_autoload_get_by_name(pa_core *c, const char*name, pa_namereg_type type) {
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);

View file

@ -34,7 +34,7 @@ typedef struct pa_autoload_entry {
pa_core *core;
uint32_t index;
char *name;
pa_namereg_type type; /* Type of the autoload entry */
pa_namereg_type_t type; /* Type of the autoload entry */
int in_action; /* Currently loaded */
char *module, *argument;
} pa_autoload_entry;
@ -42,17 +42,17 @@ typedef struct pa_autoload_entry {
/* Add a new autoload entry of the given time, with the speicified
* sink/source name, module name and argument. Return the entry's
* index in *index */
int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type type, const char*module, const char *argument, uint32_t *idx);
int pa_autoload_add(pa_core *c, const char*name, pa_namereg_type_t type, const char*module, const char *argument, uint32_t *idx);
/* Free all autoload entries */
void pa_autoload_free(pa_core *c);
int pa_autoload_remove_by_name(pa_core *c, const char*name, pa_namereg_type type);
int pa_autoload_remove_by_name(pa_core *c, const char*name, pa_namereg_type_t type);
int pa_autoload_remove_by_index(pa_core *c, uint32_t idx);
/* Request an autoload entry by its name, effectively causing a module to be loaded */
void pa_autoload_request(pa_core *c, const char *name, pa_namereg_type type);
void pa_autoload_request(pa_core *c, const char *name, pa_namereg_type_t type);
const pa_autoload_entry* pa_autoload_get_by_name(pa_core *c, const char*name, pa_namereg_type type);
const pa_autoload_entry* pa_autoload_get_by_name(pa_core *c, const char*name, pa_namereg_type_t type);
const pa_autoload_entry* pa_autoload_get_by_index(pa_core *c, uint32_t idx);
#endif

202
polyp/channelmap.c Normal file
View file

@ -0,0 +1,202 @@
/* $Id$ */
/***
This file is part of polypaudio.
polypaudio is free software; you can redistribute it 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.
polypaudio is distributed in the hope that 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 polypaudio; 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
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "channelmap.h"
pa_channel_map* pa_channel_map_init(pa_channel_map *m) {
unsigned c;
assert(m);
m->channels = 0;
for (c = 0; c < PA_CHANNELS_MAX; c++)
m->map[c] = PA_CHANNEL_POSITION_INVALID;
return m;
}
pa_channel_map* pa_channel_map_init_mono(pa_channel_map *m) {
assert(m);
pa_channel_map_init(m);
m->channels = 1;
m->map[0] = PA_CHANNEL_POSITION_MONO;
return m;
}
pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m) {
assert(m);
pa_channel_map_init(m);
m->channels = 2;
m->map[0] = PA_CHANNEL_POSITION_LEFT;
m->map[1] = PA_CHANNEL_POSITION_RIGHT;
return m;
}
pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels) {
assert(m);
assert(channels > 0);
assert(channels <= PA_CHANNELS_MAX);
pa_channel_map_init(m);
m->channels = channels;
switch (channels) {
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;
}
}
const char* pa_channel_position_to_string(pa_channel_position_t pos) {
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_AUX1] = "aux1",
[PA_CHANNEL_POSITION_AUX2] = "aux2",
[PA_CHANNEL_POSITION_AUX3] = "aux3",
[PA_CHANNEL_POSITION_AUX4] = "aux4",
[PA_CHANNEL_POSITION_AUX5] = "aux5",
[PA_CHANNEL_POSITION_AUX6] = "aux6",
[PA_CHANNEL_POSITION_AUX7] = "aux7",
[PA_CHANNEL_POSITION_AUX8] = "aux8",
[PA_CHANNEL_POSITION_AUX9] = "aux9",
[PA_CHANNEL_POSITION_AUX10] = "aux10",
[PA_CHANNEL_POSITION_AUX11] = "aux11",
[PA_CHANNEL_POSITION_AUX12] = "aux12"
};
if (pos < 0 || pos >= PA_CHANNEL_POSITION_MAX)
return NULL;
return table[pos];
}
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;
return 1;
}
char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) {
unsigned channel;
int first = 1;
char *e;
assert(s);
assert(l > 0);
assert(map);
*(e = s) = 0;
for (channel = 0; channel < map->channels && l > 1; channel++) {
l -= snprintf(e, l, "%s%u:%s",
first ? "" : " ",
channel,
pa_channel_position_to_string(map->map[channel]));
e = strchr(e, 0);
first = 0;
}
return s;
}
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;
return 1;
}

94
polyp/channelmap.h Normal file
View file

@ -0,0 +1,94 @@
#ifndef foochannelmaphfoo
#define foochannelmaphfoo
/* $Id$ */
/***
This file is part of polypaudio.
polypaudio is free software; you can redistribute it 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.
polypaudio is distributed in the hope that 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 polypaudio; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA.
***/
#include <polyp/sample.h>
#include <polyp/cdecl.h>
/** \file
* Constants and routines for channel mapping handling */
PA_C_DECL_BEGIN
typedef enum {
PA_CHANNEL_POSITION_INVALID = -1,
PA_CHANNEL_POSITION_MONO = 0,
PA_CHANNEL_POSITION_LEFT,
PA_CHANNEL_POSITION_RIGHT,
PA_CHANNEL_POSITION_FRONT_CENTER,
PA_CHANNEL_POSITION_FRONT_LEFT = PA_CHANNEL_POSITION_LEFT,
PA_CHANNEL_POSITION_FRONT_RIGHT = PA_CHANNEL_POSITION_RIGHT,
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_AUX1,
PA_CHANNEL_POSITION_AUX2,
PA_CHANNEL_POSITION_AUX3,
PA_CHANNEL_POSITION_AUX4,
PA_CHANNEL_POSITION_AUX5,
PA_CHANNEL_POSITION_AUX6,
PA_CHANNEL_POSITION_AUX7,
PA_CHANNEL_POSITION_AUX8,
PA_CHANNEL_POSITION_AUX9,
PA_CHANNEL_POSITION_AUX10,
PA_CHANNEL_POSITION_AUX11,
PA_CHANNEL_POSITION_AUX12,
PA_CHANNEL_POSITION_MAX
} pa_channel_position_t;
typedef struct pa_channel_map {
uint8_t channels;
pa_channel_position_t map[PA_CHANNELS_MAX];
} pa_channel_map;
pa_channel_map* pa_channel_map_init(pa_channel_map *m);
pa_channel_map* pa_channel_map_init_mono(pa_channel_map *m);
pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m);
pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels);
const char* pa_channel_position_to_string(pa_channel_position_t pos);
#define PA_CHANNEL_MAP_SNPRINT_MAX 64
char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map);
int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b);
int pa_channel_map_valid(const pa_channel_map *map);
PA_C_DECL_END
#endif

View file

@ -311,6 +311,7 @@ static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *bu
const char *n, *v;
pa_sink *sink;
uint32_t volume;
pa_cvolume cvolume;
if (!(n = pa_tokenizer_get(t, 1))) {
pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
@ -332,14 +333,16 @@ static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *bu
return -1;
}
pa_sink_set_volume(sink, (uint32_t) volume);
pa_cvolume_set(&cvolume, sink->sample_spec.channels, volume);
pa_sink_set_volume(sink, PA_MIXER_HARDWARE, &cvolume);
return 0;
}
static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_GCC_UNUSED int *fail) {
const char *n, *v;
pa_sink_input *si;
uint32_t volume;
pa_volume_t volume;
pa_cvolume cvolume;
uint32_t idx;
if (!(n = pa_tokenizer_get(t, 1))) {
@ -367,7 +370,8 @@ static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strb
return -1;
}
pa_sink_input_set_volume(si, (uint32_t) volume);
pa_cvolume_set(&cvolume, si->sample_spec.channels, volume);
pa_sink_input_set_volume(si, &cvolume);
return 0;
}
@ -497,7 +501,7 @@ static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *bu
return -1;
}
if (pa_scache_play_item(c, n, sink, PA_VOLUME_NORM) < 0) {
if (pa_scache_play_item(c, n, sink, NULL) < 0) {
pa_strbuf_puts(buf, "Failed to play sample.\n");
return -1;
}
@ -576,7 +580,7 @@ static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf,
}
return pa_play_file(sink, fname, PA_VOLUME_NORM);
return pa_play_file(sink, fname, NULL);
}
static int pa_cli_command_autoload_add(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, int *fail) {
@ -663,9 +667,6 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G
nl = 0;
for (s = pa_idxset_first(c->sinks, &idx); s; s = pa_idxset_next(c->sinks, &idx)) {
if (s->volume == PA_VOLUME_NORM)
continue;
if (s->owner && s->owner->auto_unload)
continue;
@ -673,8 +674,8 @@ static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, PA_G
pa_strbuf_puts(buf, "\n");
nl = 1;
}
pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", s->name, s->volume);
pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", s->name, pa_cvolume_avg(pa_sink_get_volume(s, PA_MIXER_HARDWARE)));
}

View file

@ -38,6 +38,7 @@
#include "scache.h"
#include "autoload.h"
#include "xmalloc.h"
#include "volume.h"
char *pa_module_list_to_string(pa_core *c) {
pa_strbuf *s;
@ -60,7 +61,6 @@ char *pa_client_list_to_string(pa_core *c) {
pa_strbuf *s;
pa_client *client;
uint32_t idx = PA_IDXSET_INVALID;
char tid[5];
assert(c);
s = pa_strbuf_new();
@ -69,7 +69,7 @@ char *pa_client_list_to_string(pa_core *c) {
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\ttype: <%s>\n", client->index, client->name, pa_typeid_to_string(client->typeid, tid, sizeof(tid)));
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);
@ -82,7 +82,6 @@ char *pa_sink_list_to_string(pa_core *c) {
pa_strbuf *s;
pa_sink *sink;
uint32_t idx = PA_IDXSET_INVALID;
char tid[5];
assert(c);
s = pa_strbuf_new();
@ -91,20 +90,26 @@ char *pa_sink_list_to_string(pa_core *c) {
pa_strbuf_printf(s, "%u sink(s) available.\n", pa_idxset_size(c->sinks));
for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx)) {
char ss[PA_SAMPLE_SPEC_SNPRINT_MAX];
pa_sample_spec_snprint(ss, sizeof(ss), &sink->sample_spec);
assert(sink->monitor_source);
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\tname: <%s>\n\ttype: <%s>\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%0.0f usec>\n\tmonitor_source: <%u>\n\tsample_spec: <%s>\n",
" %c index: %u\n"
"\tname: <%s>\n"
"\tdriver: <%s>\n"
"\tvolume: <%s>\n"
"\tlatency: <%0.0f usec>\n"
"\tmonitor_source: <%u>\n"
"\tsample spec: <%s>\n"
"\tchannel map: <%s>\n",
c->default_sink_name && !strcmp(sink->name, c->default_sink_name) ? '*' : ' ',
sink->index, sink->name,
pa_typeid_to_string(sink->typeid, tid, sizeof(tid)),
(unsigned) sink->volume,
pa_volume_to_dB(sink->volume),
sink->driver,
pa_cvolume_snprint(cv, sizeof(cv), pa_sink_get_volume(sink, PA_MIXER_HARDWARE)),
(double) pa_sink_get_latency(sink),
sink->monitor_source->index,
ss);
pa_sample_spec_snprint(ss, sizeof(ss), &sink->sample_spec),
pa_channel_map_snprint(cm, sizeof(cm), &sink->channel_map));
if (sink->owner)
pa_strbuf_printf(s, "\towner module: <%u>\n", sink->owner->index);
@ -119,7 +124,6 @@ char *pa_source_list_to_string(pa_core *c) {
pa_strbuf *s;
pa_source *source;
uint32_t idx = PA_IDXSET_INVALID;
char tid[5];
assert(c);
s = pa_strbuf_new();
@ -128,15 +132,24 @@ char *pa_source_list_to_string(pa_core *c) {
pa_strbuf_printf(s, "%u source(s) available.\n", pa_idxset_size(c->sources));
for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) {
char ss[PA_SAMPLE_SPEC_SNPRINT_MAX];
pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec);
pa_strbuf_printf(s, " %c index: %u\n\tname: <%s>\n\ttype: <%s>\n\tlatency: <%0.0f usec>\n\tsample_spec: <%s>\n",
c->default_source_name && !strcmp(source->name, c->default_source_name) ? '*' : ' ',
source->index,
source->name,
pa_typeid_to_string(source->typeid, tid, sizeof(tid)),
(double) pa_source_get_latency(source),
ss);
char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
pa_strbuf_printf(
s,
" %c index: %u\n"
"\tname: <%s>\n"
"\tdriver: <%s>\n"
"\tlatency: <%0.0f usec>\n"
"\tsample spec: <%s>\n"
"\tchannel map: <%s>\n",
c->default_source_name && !strcmp(source->name, c->default_source_name) ? '*' : ' ',
source->index,
source->name,
source->driver,
(double) pa_source_get_latency(source),
pa_sample_spec_snprint(ss, sizeof(ss), &source->sample_spec),
pa_channel_map_snprint(cm, sizeof(cm), &source->channel_map));
if (source->monitor_of)
pa_strbuf_printf(s, "\tmonitor_of: <%u>\n", source->monitor_of->index);
@ -154,7 +167,6 @@ char *pa_source_output_list_to_string(pa_core *c) {
pa_strbuf *s;
pa_source_output *o;
uint32_t idx = PA_IDXSET_INVALID;
char tid[5];
static const char* const state_table[] = {
"RUNNING",
"CORKED",
@ -168,23 +180,28 @@ char *pa_source_output_list_to_string(pa_core *c) {
pa_strbuf_printf(s, "%u source outputs(s) available.\n", pa_idxset_size(c->source_outputs));
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];
const char *rm;
pa_sample_spec_snprint(ss, sizeof(ss), &o->sample_spec);
char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
assert(o->source);
if (!(rm = pa_resample_method_to_string(pa_source_output_get_resample_method(o))))
rm = "invalid";
pa_strbuf_printf(
s, " index: %u\n\tname: '%s'\n\ttype: <%s>\n\tstate: %s\n\tsource: <%u> '%s'\n\tsample_spec: <%s>\n\tresample method: %s\n",
s,
" index: %u\n"
"\tname: '%s'\n"
"\tdriver: <%s>\n"
"\tstate: %s\n"
"\tsource: <%u> '%s'\n"
"\tsample spec: <%s>\n"
"\tchannel map: <%s>\n"
"\tresample method: %s\n",
o->index,
o->name,
pa_typeid_to_string(o->typeid, tid, sizeof(tid)),
o->driver,
state_table[o->state],
o->source->index, o->source->name,
ss,
rm);
pa_sample_spec_snprint(ss, sizeof(ss), &o->sample_spec),
pa_channel_map_snprint(cm, sizeof(cm), &o->channel_map),
pa_resample_method_to_string(pa_source_output_get_resample_method(o)));
if (o->owner)
pa_strbuf_printf(s, "\towner module: <%u>\n", o->owner->index);
if (o->client)
@ -198,7 +215,6 @@ char *pa_sink_input_list_to_string(pa_core *c) {
pa_strbuf *s;
pa_sink_input *i;
uint32_t idx = PA_IDXSET_INVALID;
char tid[5];
static const char* const state_table[] = {
"RUNNING",
"CORKED",
@ -212,26 +228,32 @@ char *pa_sink_input_list_to_string(pa_core *c) {
pa_strbuf_printf(s, "%u sink input(s) available.\n", pa_idxset_size(c->sink_inputs));
for (i = pa_idxset_first(c->sink_inputs, &idx); i; i = pa_idxset_next(c->sink_inputs, &idx)) {
char ss[PA_SAMPLE_SPEC_SNPRINT_MAX];
const char *rm;
char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
if (!(rm = pa_resample_method_to_string(pa_sink_input_get_resample_method(i))))
rm = "invalid";
pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec);
assert(i->sink);
pa_strbuf_printf(
s, " index: %u\n\tname: <%s>\n\ttype: <%s>\n\tstate: %s\n\tsink: <%u> '%s'\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%0.0f usec>\n\tsample_spec: <%s>\n\tresample method: %s\n",
s,
" index: %u\n"
"\tname: <%s>\n"
"\tdriver: <%s>\n"
"\tstate: %s\n"
"\tsink: <%u> '%s'\n"
"\tvolume: <%s>\n"
"\tlatency: <%0.0f usec>\n"
"\tsample spec: <%s>\n"
"\tchannel map: <%s>\n"
"\tresample method: %s\n",
i->index,
i->name,
pa_typeid_to_string(i->typeid, tid, sizeof(tid)),
i->driver,
state_table[i->state],
i->sink->index, i->sink->name,
(unsigned) i->volume,
pa_volume_to_dB(i->volume),
pa_cvolume_snprint(cv, sizeof(cv), pa_sink_input_get_volume(i)),
(double) pa_sink_input_get_latency(i),
ss,
rm);
pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec),
pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
pa_resample_method_to_string(pa_sink_input_get_resample_method(i)));
if (i->owner)
pa_strbuf_printf(s, "\towner module: <%u>\n", i->owner->index);
@ -257,21 +279,32 @@ char *pa_scache_list_to_string(pa_core *c) {
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";
char ss[PA_SAMPLE_SPEC_SNPRINT_MAX] = "n/a", cv[PA_CVOLUME_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
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\tindex: <%u>\n\tsample_spec: <%s>\n\tlength: <%u>\n\tduration: <%0.1fs>\n\tvolume: <0x%04x>\n\tlazy: %s\n\tfilename: %s\n",
s,
" name: <%s>\n"
"\tindex: <%u>\n"
"\tsample spec: <%s>\n"
"\tchannel map: <%s>\n"
"\tlength: <%u>\n"
"\tduration: <%0.1fs>\n"
"\tvolume: <%s>\n"
"\tlazy: %s\n"
"\tfilename: %s\n",
e->name,
e->index,
ss,
cm,
e->memchunk.memblock ? e->memchunk.length : 0,
l,
e->volume,
pa_cvolume_snprint(cv, sizeof(cv), &e->volume),
e->lazy ? "yes" : "no",
e->filename ? e->filename : "n/a");
}

View file

@ -45,7 +45,6 @@
#include "log.h"
#define PROMPT ">>> "
#define PA_TYPEID_CLI PA_TYPEID_MAKE('C', 'L', 'I', '_')
struct pa_cli {
pa_core *core;
@ -76,7 +75,7 @@ pa_cli* pa_cli_new(pa_core *core, pa_iochannel *io, pa_module *m) {
c->eof_callback = NULL;
pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname));
c->client = pa_client_new(core, PA_TYPEID_CLI, cname);
c->client = pa_client_new(core, __FILE__, cname);
assert(c->client);
c->client->kill = client_kill;
c->client->userdata = c;

View file

@ -33,16 +33,16 @@
#include "subscribe.h"
#include "log.h"
pa_client *pa_client_new(pa_core *core, pa_typeid_t typeid, const char *name) {
pa_client *pa_client_new(pa_core *core, const char *name, const char *driver) {
pa_client *c;
int r;
assert(core);
c = pa_xmalloc(sizeof(pa_client));
c->name = pa_xstrdup(name);
c->driver = pa_xstrdup(driver);
c->owner = NULL;
c->core = core;
c->typeid = typeid;
c->kill = NULL;
c->userdata = NULL;
@ -68,8 +68,8 @@ void pa_client_free(pa_client *c) {
pa_log_info(__FILE__": freed %u \"%s\"\n", c->index, c->name);
pa_subscription_post(c->core, PA_SUBSCRIPTION_EVENT_CLIENT|PA_SUBSCRIPTION_EVENT_REMOVE, c->index);
pa_xfree(c->name);
pa_xfree(c->driver);
pa_xfree(c);
}
void pa_client_kill(pa_client *c) {

View file

@ -24,7 +24,6 @@
#include "core.h"
#include "module.h"
#include "typeid.h"
/* Every connection to the server should have a pa_client
* attached. That way the user may generate a listing of all connected
@ -34,17 +33,16 @@ typedef struct pa_client pa_client;
struct pa_client {
uint32_t index;
pa_typeid_t typeid;
pa_module *owner;
char *name;
char *name, *driver;
pa_core *core;
void (*kill)(pa_client *c);
void *userdata;
};
pa_client *pa_client_new(pa_core *c, pa_typeid_t typeid, const char *name);
pa_client *pa_client_new(pa_core *c, const char *name, const char *driver);
/* This function should be called only by the code that created the client */
void pa_client_free(pa_client *c);

View file

@ -70,7 +70,7 @@ struct pa_core {
pa_time_event *scache_auto_unload_event;
pa_resample_method resample_method;
pa_resample_method_t resample_method;
};
pa_core* pa_core_new(pa_mainloop_api *m);

View file

@ -126,7 +126,7 @@ int pa_daemon_conf_set_log_level(pa_daemon_conf *c, const char *string) {
if (u >= PA_LOG_LEVEL_MAX)
return -1;
c->log_level = (pa_log_level) u;
c->log_level = (pa_log_level_t) u;
} else if (pa_startswith(string, "debug"))
c->log_level = PA_LOG_DEBUG;
else if (pa_startswith(string, "info"))

View file

@ -33,11 +33,11 @@ typedef enum pa_daemon_conf_cmd {
PA_CMD_DUMP_MODULES,
PA_CMD_KILL,
PA_CMD_CHECK
} pa_daemon_conf_cmd;
} pa_daemon_conf_cmd_t;
/* A structure containing configuration data for the Polypaudio server . */
typedef struct pa_daemon_conf {
pa_daemon_conf_cmd cmd;
pa_daemon_conf_cmd_t cmd;
int daemonize,
fail,
high_priority,
@ -48,8 +48,8 @@ typedef struct pa_daemon_conf {
auto_log_target,
use_pid_file;
char *script_commands, *dl_search_path, *default_script_file;
pa_log_target log_target;
pa_log_level log_level;
pa_log_target_t log_target;
pa_log_level_t log_level;
int resample_method;
char *config_file;
} pa_daemon_conf;

View file

@ -1,4 +1,4 @@
/* $Id: dllmain.c 317 2004-12-11 00:10:41Z lennart $ */
/* $Id$ */
/***
This file is part of polypaudio.

View file

@ -38,9 +38,9 @@ struct pa_io_event {
GSource *source;
GIOCondition io_condition;
int fd;
void (*callback) (pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata);
void (*callback) (pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata);
void *userdata;
void (*destroy_callback) (pa_mainloop_api *m, pa_io_event*e, void *userdata);
void (*destroy_callback) (pa_mainloop_api *m, pa_io_event *e, void *userdata);
pa_io_event *next, *prev;
};
@ -76,9 +76,9 @@ struct pa_glib_mainloop {
static void schedule_free_dead_events(pa_glib_mainloop *g);
static void glib_io_enable(pa_io_event*e, pa_io_event_flags f);
static void glib_io_enable(pa_io_event*e, pa_io_event_flags_t f);
static pa_io_event* glib_io_new(pa_mainloop_api*m, int fd, pa_io_event_flags f, void (*callback) (pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags f, void *userdata), void *userdata) {
static pa_io_event* glib_io_new(pa_mainloop_api*m, int fd, pa_io_event_flags_t f, void (*callback) (pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags_t f, void *userdata), void *userdata) {
pa_io_event *e;
pa_glib_mainloop *g;
@ -111,7 +111,7 @@ static pa_io_event* glib_io_new(pa_mainloop_api*m, int fd, pa_io_event_flags f,
/* The callback GLIB calls whenever an IO condition is met */
static gboolean io_cb(GIOChannel *source, GIOCondition condition, gpointer data) {
pa_io_event *e = data;
pa_io_event_flags f;
pa_io_event_flags_t f;
assert(source && e && e->io_channel == source);
f = (condition & G_IO_IN ? PA_IO_EVENT_INPUT : 0) |
@ -123,7 +123,7 @@ static gboolean io_cb(GIOChannel *source, GIOCondition condition, gpointer data)
return TRUE;
}
static void glib_io_enable(pa_io_event*e, pa_io_event_flags f) {
static void glib_io_enable(pa_io_event*e, pa_io_event_flags_t f) {
GIOCondition c;
assert(e && !e->dead);

View file

@ -39,7 +39,7 @@ struct pa_io_event {
guint source;
GIOCondition io_condition;
int fd;
void (*callback) (pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata);
void (*callback) (pa_mainloop_api*m, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata);
void *userdata;
void (*destroy_callback) (pa_mainloop_api *m, pa_io_event*e, void *userdata);
pa_io_event *next, *prev;
@ -76,9 +76,9 @@ struct pa_glib_mainloop {
static void schedule_free_dead_events(pa_glib_mainloop *g);
static void glib_io_enable(pa_io_event*e, pa_io_event_flags f);
static void glib_io_enable(pa_io_event*e, pa_io_event_flags_t f);
static pa_io_event* glib_io_new(pa_mainloop_api*m, int fd, pa_io_event_flags f, void (*callback) (pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags f, void *userdata), void *userdata) {
static pa_io_event* glib_io_new(pa_mainloop_api*m, int fd, pa_io_event_flags_t f, void (*callback) (pa_mainloop_api*m, pa_io_event*e, int fd, pa_io_event_flags_t f, void *userdata), void *userdata) {
pa_io_event *e;
pa_glib_mainloop *g;
@ -110,7 +110,7 @@ static pa_io_event* glib_io_new(pa_mainloop_api*m, int fd, pa_io_event_flags f,
static gboolean io_cb(GIOChannel *source, GIOCondition condition, gpointer data) {
pa_io_event *e = data;
pa_io_event_flags f;
pa_io_event_flags_t f;
assert(source && e && e->io_channel == source);
f = (condition & G_IO_IN ? PA_IO_EVENT_INPUT : 0) |
@ -122,7 +122,7 @@ static gboolean io_cb(GIOChannel *source, GIOCondition condition, gpointer data)
return TRUE;
}
static void glib_io_enable(pa_io_event*e, pa_io_event_flags f) {
static void glib_io_enable(pa_io_event*e, pa_io_event_flags_t f) {
GIOCondition c;
assert(e && !e->dead);

View file

@ -1,4 +1,4 @@
/* $Id: inet_ntop.c 428 2006-01-09 16:50:39Z ossman $ */
/* $Id$ */
/***
This file is part of polypaudio.

View file

@ -55,7 +55,7 @@ static void enable_mainloop_sources(pa_iochannel *io) {
assert(io);
if (io->input_event == io->output_event && io->input_event) {
pa_io_event_flags f = PA_IO_EVENT_NULL;
pa_io_event_flags_t f = PA_IO_EVENT_NULL;
assert(io->input_event);
if (!io->readable)
@ -72,7 +72,7 @@ static void enable_mainloop_sources(pa_iochannel *io) {
}
}
static void callback(pa_mainloop_api* m, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata) {
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;

View file

@ -38,9 +38,9 @@
#define ENV_LOGLEVEL "POLYP_LOG"
static char *log_ident = NULL;
static pa_log_target log_target = PA_LOG_STDERR;
static void (*user_log_func)(pa_log_level l, const char *s) = NULL;
static pa_log_level maximal_level = PA_LOG_NOTICE;
static pa_log_target_t log_target = PA_LOG_STDERR;
static void (*user_log_func)(pa_log_level_t l, const char *s) = NULL;
static pa_log_level_t maximal_level = PA_LOG_NOTICE;
#ifdef HAVE_SYSLOG_H
static const int level_to_syslog[] = {
@ -59,18 +59,18 @@ void pa_log_set_ident(const char *p) {
log_ident = pa_xstrdup(p);
}
void pa_log_set_maximal_level(pa_log_level l) {
void pa_log_set_maximal_level(pa_log_level_t l) {
assert(l < PA_LOG_LEVEL_MAX);
maximal_level = l;
}
void pa_log_set_target(pa_log_target t, void (*func)(pa_log_level l, const char*s)) {
void pa_log_set_target(pa_log_target_t t, void (*func)(pa_log_level_t l, const char*s)) {
assert(t == PA_LOG_USER || !func);
log_target = t;
user_log_func = func;
}
void pa_log_with_levelv(pa_log_level level, const char *format, va_list ap) {
void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap) {
const char *e;
assert(level < PA_LOG_LEVEL_MAX);
@ -107,44 +107,44 @@ void pa_log_with_levelv(pa_log_level level, const char *format, va_list ap) {
}
void pa_log_with_level(pa_log_level level, const char *format, ...) {
void pa_log_level(pa_log_level_t level, const char *format, ...) {
va_list ap;
va_start(ap, format);
pa_log_with_levelv(level, format, ap);
pa_log_levelv(level, format, ap);
va_end(ap);
}
void pa_log_debug(const char *format, ...) {
va_list ap;
va_start(ap, format);
pa_log_with_levelv(PA_LOG_DEBUG, format, ap);
pa_log_levelv(PA_LOG_DEBUG, format, ap);
va_end(ap);
}
void pa_log_info(const char *format, ...) {
va_list ap;
va_start(ap, format);
pa_log_with_levelv(PA_LOG_INFO, format, ap);
pa_log_levelv(PA_LOG_INFO, format, ap);
va_end(ap);
}
void pa_log_notice(const char *format, ...) {
va_list ap;
va_start(ap, format);
pa_log_with_levelv(PA_LOG_INFO, format, ap);
pa_log_levelv(PA_LOG_INFO, format, ap);
va_end(ap);
}
void pa_log_warn(const char *format, ...) {
va_list ap;
va_start(ap, format);
pa_log_with_levelv(PA_LOG_WARN, format, ap);
pa_log_levelv(PA_LOG_WARN, format, ap);
va_end(ap);
}
void pa_log_error(const char *format, ...) {
va_list ap;
va_start(ap, format);
pa_log_with_levelv(PA_LOG_ERROR, format, ap);
pa_log_levelv(PA_LOG_ERROR, format, ap);
va_end(ap);
}

View file

@ -33,7 +33,7 @@ typedef enum pa_log_target {
PA_LOG_SYSLOG,
PA_LOG_USER, /* to user specified function */
PA_LOG_NULL /* to /dev/null */
} pa_log_target;
} pa_log_target_t;
typedef enum pa_log_level {
PA_LOG_ERROR = 0, /* Error messages */
@ -42,16 +42,16 @@ typedef enum pa_log_level {
PA_LOG_INFO = 3, /* Info messages */
PA_LOG_DEBUG = 4, /* debug message */
PA_LOG_LEVEL_MAX
} pa_log_level;
} pa_log_level_t;
/* Set an identification for the current daemon. Used when logging to syslog. */
void pa_log_set_ident(const char *p);
/* Set another log target. If t is PA_LOG_USER you may specify a function that is called every log string */
void pa_log_set_target(pa_log_target t, void (*func)(pa_log_level, const char*s));
void pa_log_set_target(pa_log_target_t t, void (*func)(pa_log_level_t t, const char*s));
/* Minimal log level */
void pa_log_set_maximal_level(pa_log_level l);
void pa_log_set_maximal_level(pa_log_level_t l);
/* Do a log line */
void pa_log_debug(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2);
@ -60,9 +60,9 @@ void pa_log_notice(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2);
void pa_log_warn(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2);
void pa_log_error(const char *format, ...) PA_GCC_PRINTF_ATTR(1,2);
void pa_log_with_level(pa_log_level level, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3);
void pa_log_level(pa_log_level_t level, const char *format, ...) PA_GCC_PRINTF_ATTR(2,3);
void pa_log_with_levelv(pa_log_level level, const char *format, va_list ap);
void pa_log_levelv(pa_log_level_t level, const char *format, va_list ap);
#define pa_log pa_log_error

View file

@ -37,6 +37,7 @@
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <liboil/liboil.h>
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
@ -386,6 +387,8 @@ int main(int argc, char *argv[]) {
pa_signal_new(SIGHUP, signal_callback, c);
#endif
oil_init();
r = pa_cpu_limit_init(pa_mainloop_get_api(mainloop));
assert(r == 0);

View file

@ -51,7 +51,7 @@ typedef enum pa_io_event_flags {
PA_IO_EVENT_OUTPUT = 2, /**< Output event */
PA_IO_EVENT_HANGUP = 4, /**< Hangup event */
PA_IO_EVENT_ERROR = 8 /**< Error event */
} pa_io_event_flags;
} pa_io_event_flags_t;
/** \pa_io_event
* An opaque IO event source object */
@ -73,10 +73,10 @@ struct pa_mainloop_api {
void *userdata;
/** Create a new IO event source object */
pa_io_event* (*io_new)(pa_mainloop_api*a, int fd, pa_io_event_flags events, void (*callback) (pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags events, void *userdata), void *userdata);
pa_io_event* (*io_new)(pa_mainloop_api*a, int fd, pa_io_event_flags_t events, void (*callback) (pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata), void *userdata);
/** Enable or disable IO events on this object */
void (*io_enable)(pa_io_event* e, pa_io_event_flags events);
void (*io_enable)(pa_io_event* e, pa_io_event_flags_t events);
/** Free a IO event source object */
void (*io_free)(pa_io_event* e);

View file

@ -119,7 +119,7 @@ static void defer(pa_mainloop_api*a, PA_GCC_UNUSED pa_defer_event*e, PA_GCC_UNUS
}
}
static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags f, PA_GCC_UNUSED void *userdata) {
static void callback(pa_mainloop_api*a, pa_io_event*e, int fd, pa_io_event_flags_t f, PA_GCC_UNUSED void *userdata) {
ssize_t r;
int sig;
assert(a && e && f == PA_IO_EVENT_INPUT && e == io_event && fd == signal_pipe[0]);

View file

@ -51,7 +51,7 @@ static GMainLoop* glib_main_loop = NULL;
static pa_defer_event *de;
static void iocb(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata) {
static void iocb(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
unsigned char c;
read(fd, &c, sizeof(c));
fprintf(stderr, "IO EVENT: %c\n", c < 32 ? '.' : c);

View file

@ -50,8 +50,8 @@ struct pa_io_event {
pa_mainloop *mainloop;
int dead;
int fd;
pa_io_event_flags events;
void (*callback) (pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata);
pa_io_event_flags_t events;
void (*callback) (pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata);
struct pollfd *pollfd;
void *userdata;
void (*destroy_callback) (pa_mainloop_api*a, pa_io_event *e, void *userdata);
@ -91,7 +91,13 @@ struct pa_mainloop {
};
/* IO events */
static pa_io_event* mainloop_io_new(pa_mainloop_api*a, int fd, pa_io_event_flags events, void (*callback) (pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags events, void *userdata), void *userdata) {
static pa_io_event* mainloop_io_new(
pa_mainloop_api*a,
int fd,
pa_io_event_flags_t events,
void (*callback) (pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t events, void *userdata),
void *userdata) {
pa_mainloop *m;
pa_io_event *e;
@ -135,7 +141,7 @@ static pa_io_event* mainloop_io_new(pa_mainloop_api*a, int fd, pa_io_event_flags
return e;
}
static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags events) {
static void mainloop_io_enable(pa_io_event *e, pa_io_event_flags_t events) {
assert(e && e->mainloop);
e->events = events;

View file

@ -31,12 +31,12 @@
* memory blocks. */
/* The type of memory this block points to */
typedef enum {
typedef enum pa_memblock_type {
PA_MEMBLOCK_FIXED, /* data is a pointer to fixed memory that needs not to be freed */
PA_MEMBLOCK_APPENDED, /* The most common kind: the data is appended to the memory block */
PA_MEMBLOCK_DYNAMIC, /* data is a pointer to some memory allocated with pa_xmalloc() */
PA_MEMBLOCK_USER /* User supplied memory, to be freed with free_cb */
} pa_memblock_type ;
} pa_memblock_type_t;
/* A structure of keeping memory block statistics */
/* Maintains statistics about memory blocks */
@ -49,7 +49,7 @@ typedef struct pa_memblock_stat {
} pa_memblock_stat;
typedef struct pa_memblock {
pa_memblock_type type;
pa_memblock_type_t type;
unsigned ref; /* the reference counter */
int read_only; /* boolean */
size_t length;

View file

@ -51,8 +51,6 @@ PA_MODULE_DESCRIPTION("ALSA Sink")
PA_MODULE_VERSION(PACKAGE_VERSION)
PA_MODULE_USAGE("sink_name=<name for the sink> device=<ALSA device> format=<sample format> channels=<number of channels> rate=<sample rate> fragments=<number of fragments> fragment_size=<fragment size>")
#define PA_TYPEID_ALSA PA_TYPEID_MAKE('A', 'L', 'S', 'A')
struct userdata {
snd_pcm_t *pcm_handle;
pa_sink *sink;
@ -142,7 +140,7 @@ static void do_write(struct userdata *u) {
}
}
static void io_callback(pa_mainloop_api*a, pa_io_event *e, PA_GCC_UNUSED int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) {
static void io_callback(pa_mainloop_api*a, pa_io_event *e, PA_GCC_UNUSED int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) {
struct userdata *u = userdata;
assert(u && a && e);
@ -220,7 +218,7 @@ int pa__init(pa_core *c, pa_module*m) {
goto fail;
}
u->sink = pa_sink_new(c, PA_TYPEID_ALSA, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss);
u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL);
assert(u->sink);
u->sink->get_latency = sink_get_latency_cb;
@ -236,7 +234,7 @@ int pa__init(pa_core *c, pa_module*m) {
u->frame_size = frame_size;
u->fragment_size = period_size;
pa_log(__FILE__": using %u fragments of size %u bytes.\n", periods, u->fragment_size);
pa_log_info(__FILE__": using %u fragments of size %u bytes.\n", periods, u->fragment_size);
u->silence.memblock = pa_memblock_new(u->silence.length = u->fragment_size, c->memblock_stat);
assert(u->silence.memblock);

View file

@ -51,8 +51,6 @@ PA_MODULE_DESCRIPTION("ALSA Source")
PA_MODULE_VERSION(PACKAGE_VERSION)
PA_MODULE_USAGE("source_name=<name for the source> device=<ALSA device> format=<sample format> channels=<number of channels> rate=<sample rate> fragments=<number of fragments> fragment_size=<fragment size>")
#define PA_TYPEID_ALSA PA_TYPEID_MAKE('A', 'L', 'S', 'A')
struct userdata {
snd_pcm_t *pcm_handle;
pa_source *source;
@ -142,7 +140,7 @@ static void do_read(struct userdata *u) {
}
}
static void io_callback(pa_mainloop_api*a, pa_io_event *e, PA_GCC_UNUSED int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) {
static void io_callback(pa_mainloop_api*a, pa_io_event *e, PA_GCC_UNUSED int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) {
struct userdata *u = userdata;
assert(u && a && e);
@ -211,7 +209,7 @@ int pa__init(pa_core *c, pa_module*m) {
goto fail;
}
u->source = pa_source_new(c, PA_TYPEID_ALSA, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss);
u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL);
assert(u->source);
u->source->userdata = u;

View file

@ -43,8 +43,6 @@ PA_MODULE_DESCRIPTION("Combine multiple sinks to one")
PA_MODULE_VERSION(PACKAGE_VERSION)
PA_MODULE_USAGE("sink_name=<name for the sink> master=<master sink> slaves=<slave sinks> adjust_time=<seconds> resample_method=<method>")
#define PA_TYPEID_COMBINE PA_TYPEID_MAKE('C', 'M', 'B', 'N')
#define DEFAULT_SINK_NAME "combined"
#define MEMBLOCKQ_MAXLENGTH (1024*170)
#define RENDER_SIZE (1024*10)
@ -216,7 +214,7 @@ static struct output *output_new(struct userdata *u, pa_sink *sink, int resample
o->memblockq = pa_memblockq_new(MEMBLOCKQ_MAXLENGTH, MEMBLOCKQ_MAXLENGTH, pa_frame_size(&u->sink->sample_spec), 0, 0, sink->core->memblock_stat);
snprintf(t, sizeof(t), "%s: output #%u", u->sink->name, u->n_outputs+1);
if (!(o->sink_input = pa_sink_input_new(sink, PA_TYPEID_COMBINE, t, &u->sink->sample_spec, 1, resample_method)))
if (!(o->sink_input = pa_sink_input_new(sink, __FILE__, t, &u->sink->sample_spec, &u->sink->channel_map, 1, resample_method)))
goto fail;
o->sink_input->get_latency = sink_input_get_latency_cb;
@ -327,7 +325,7 @@ int pa__init(pa_core *c, pa_module*m) {
goto fail;
}
if (!(u->sink = pa_sink_new(c, PA_TYPEID_COMBINE, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &master_sink->sample_spec))) {
if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &master_sink->sample_spec, &master_sink->channel_map))) {
pa_log(__FILE__": failed to create sink\n");
goto fail;
}

View file

@ -46,14 +46,12 @@
#include "authkey.h"
PA_MODULE_AUTHOR("Lennart Poettering")
PA_MODULE_DESCRIPTION("Esound ")
PA_MODULE_DESCRIPTION("ESOUND Sink")
PA_MODULE_VERSION(PACKAGE_VERSION)
PA_MODULE_USAGE("sink_name=<name for the sink> server=<address> cookie=<filename> format=<sample format> channels=<number of channels> rate=<sample rate>")
#define DEFAULT_SINK_NAME "esound_output"
#define PA_TYPEID_ESOUND_SINK PA_TYPEID_MAKE('E', 'S', 'D', 'S')
struct userdata {
pa_core *core;
@ -354,7 +352,7 @@ int pa__init(pa_core *c, pa_module*m) {
u->state = STATE_AUTH;
u->latency = 0;
if (!(u->sink = pa_sink_new(c, PA_TYPEID_ESOUND_SINK, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) {
if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) {
pa_log(__FILE__": failed to create sink.\n");
goto fail;
}

View file

@ -61,7 +61,7 @@ struct userdata {
static int lirc_in_use = 0;
static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags events, void*userdata) {
static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void*userdata) {
struct userdata *u = userdata;
char *name = NULL, *code = NULL;
assert(io);
@ -109,26 +109,45 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC
if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1)))
pa_log(__FILE__": failed to get sink '%s'\n", u->sink_name);
else {
double v = pa_volume_to_user(s->volume);
pa_volume_t v = pa_cvolume_avg(pa_sink_get_volume(s, PA_MIXER_HARDWARE));
pa_cvolume cv;
#define DELTA (PA_VOLUME_NORM/20)
switch (volchange) {
case UP: v += .05; break;
case DOWN: v -= .05; break;
case MUTE: v = 0; break;
case RESET: v = 1; break;
case UP:
v += PA_VOLUME_NORM/20;
break;
case DOWN:
if (v > DELTA)
v -= DELTA;
else
v = PA_VOLUME_MUTED;
break;
case MUTE:
v = PA_VOLUME_MUTED;
break;
case RESET:
v = PA_VOLUME_NORM;
break;
case MUTE_TOGGLE: {
if (v > 0) {
u->mute_toggle_save = v;
v = 0;
v = PA_VOLUME_MUTED;
} else
v = u->mute_toggle_save;
}
default:
;
}
pa_sink_set_volume(s, pa_volume_from_user(v));
pa_cvolume_set(&cv, PA_CHANNELS_MAX, v);
pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv);
}
}
}

View file

@ -154,7 +154,7 @@ finish:
return ret;
}
static void callback(pa_core *c, pa_subscription_event_type t, uint32_t idx, void *userdata) {
static void callback(pa_core *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
struct userdata *u = userdata;
pa_sink_input *si;
struct rule *r;
@ -171,8 +171,10 @@ static void callback(pa_core *c, pa_subscription_event_type t, uint32_t idx, voi
for (r = u->rules; r; r = r->next) {
if (!regexec(&r->regex, si->name, 0, NULL, 0)) {
pa_cvolume cv;
pa_log_debug(__FILE__": changing volume of sink input '%s' to 0x%03x\n", si->name, r->volume);
pa_sink_input_set_volume(si, r->volume);
pa_cvolume_set(&cv, r->volume, si->sample_spec.channels);
pa_sink_input_set_volume(si, &cv);
}
}
}

View file

@ -74,7 +74,7 @@ struct userdata {
float mute_toggle_save;
};
static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags events, void*userdata) {
static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags_t events, void*userdata) {
struct userdata *u = userdata;
assert(io);
assert(u);
@ -109,16 +109,28 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC
if (!(s = pa_namereg_get(u->module->core, u->sink_name, PA_NAMEREG_SINK, 1)))
pa_log(__FILE__": failed to get sink '%s'\n", u->sink_name);
else {
double v = pa_volume_to_user(s->volume);
pa_volume_t v = pa_cvolume_avg(pa_sink_get_volume(s, PA_MIXER_HARDWARE));
pa_cvolume cv;
#define DELTA (PA_VOLUME_NORM/20)
switch (volchange) {
case UP: v += .05; break;
case DOWN: v -= .05; break;
case UP:
v += DELTA;
break;
case DOWN:
if (v > DELTA)
v -= DELTA;
else
v = PA_VOLUME_MUTED;
break;
case MUTE_TOGGLE: {
if (v > 0) {
u->mute_toggle_save = v;
v = 0;
v = PA_VOLUME_MUTED;
} else
v = u->mute_toggle_save;
}
@ -126,7 +138,8 @@ static void io_callback(pa_mainloop_api *io, PA_GCC_UNUSED pa_io_event *e, PA_GC
;
}
pa_sink_set_volume(s, pa_volume_from_user(v));
pa_cvolume_set(&cv, PA_CHANNELS_MAX, v);
pa_sink_set_volume(s, PA_MIXER_HARDWARE, &cv);
}
}
}

View file

@ -49,8 +49,6 @@ PA_MODULE_USAGE("format=<sample format> channels=<number of channels> rate=<samp
#define DEFAULT_SINK_NAME "null"
#define PA_TYPEID_NULL PA_TYPEID_MAKE('N', 'U', 'L', 'L')
struct userdata {
pa_core *core;
pa_module *module;
@ -108,7 +106,7 @@ int pa__init(pa_core *c, pa_module*m) {
u->module = m;
m->userdata = u;
if (!(u->sink = pa_sink_new(c, PA_TYPEID_NULL, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) {
if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) {
pa_log(__FILE__": failed to create sink.\n");
goto fail;
}

View file

@ -53,8 +53,6 @@ PA_MODULE_DESCRIPTION("OSS Sink/Source (mmap)")
PA_MODULE_VERSION(PACKAGE_VERSION)
PA_MODULE_USAGE("sink_name=<name for the sink> source_name=<name for the source> device=<OSS device> record=<enable source?> playback=<enable sink?> format=<sample format> channels=<number of channels> rate=<sample rate> fragments=<number of fragments> fragment_size=<fragment size>")
#define PA_TYPEID_OSS_MMAP PA_TYPEID_MAKE('O', 'S', 'S', 'M')
struct userdata {
pa_sink *sink;
pa_source *source;
@ -204,7 +202,7 @@ static void do_read(struct userdata *u) {
in_clear_memblocks(u, u->in_fragments/2);
}
static void io_callback(pa_mainloop_api *m, pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags f, void *userdata) {
static void io_callback(pa_mainloop_api *m, pa_io_event *e, PA_GCC_UNUSED int fd, pa_io_event_flags_t f, void *userdata) {
struct userdata *u = userdata;
assert (u && u->core->mainloop == m && u->io_event == e);
@ -304,7 +302,7 @@ int pa__init(pa_core *c, pa_module*m) {
}
} else {
u->source = pa_source_new(c, PA_TYPEID_OSS_MMAP, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &u->sample_spec);
u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &u->sample_spec, NULL);
assert(u->source);
u->source->userdata = u;
pa_source_set_owner(u->source, m);
@ -336,7 +334,7 @@ int pa__init(pa_core *c, pa_module*m) {
} else {
pa_silence_memory(u->out_mmap, u->out_mmap_length, &u->sample_spec);
u->sink = pa_sink_new(c, PA_TYPEID_OSS_MMAP, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &u->sample_spec);
u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &u->sample_spec, NULL);
assert(u->sink);
u->sink->get_latency = sink_get_latency_cb;
u->sink->userdata = u;

View file

@ -52,8 +52,6 @@ PA_MODULE_DESCRIPTION("OSS Sink/Source")
PA_MODULE_VERSION(PACKAGE_VERSION)
PA_MODULE_USAGE("sink_name=<name for the sink> source_name=<name for the source> device=<OSS device> record=<enable source?> playback=<enable sink?> format=<sample format> channels=<number of channels> rate=<sample rate> fragments=<number of fragments> fragment_size=<fragment size>")
#define PA_TYPEID_OSS PA_TYPEID_MAKE('O', 'S', 'S', '_')
struct userdata {
pa_sink *sink;
pa_source *source;
@ -222,7 +220,7 @@ static pa_usec_t sink_get_latency_cb(pa_sink *s) {
assert(s && u && u->sink);
if (ioctl(u->fd, SNDCTL_DSP_GETODELAY, &arg) < 0) {
pa_log_info(__FILE__": device doesn't support SNDCTL_DSP_GETODELAY.\n");
pa_log_info(__FILE__": device doesn't support SNDCTL_DSP_GETODELAY: %s\n", strerror(errno));
s->get_latency = NULL;
return 0;
}
@ -254,6 +252,46 @@ static pa_usec_t source_get_latency_cb(pa_source *s) {
return pa_bytes_to_usec(info.bytes, &s->sample_spec);
}
static int sink_get_hw_volume(pa_sink *s) {
struct userdata *u = s->userdata;
char cv[PA_CVOLUME_SNPRINT_MAX];
unsigned vol;
if (ioctl(u->fd, SOUND_MIXER_READ_PCM, &vol) < 0) {
pa_log_info(__FILE__": device doesn't support reading mixer settings: %s\n", strerror(errno));
s->get_hw_volume = NULL;
return -1;
}
s->hw_volume.values[0] = ((vol & 0xFF) * PA_VOLUME_NORM) / 100;
if ((s->hw_volume.channels = s->sample_spec.channels) >= 2)
s->hw_volume.values[1] = (((vol >> 8) & 0xFF) * PA_VOLUME_NORM) / 100;
pa_log_info(__FILE__": Read mixer settings: %s\n", pa_cvolume_snprint(cv, sizeof(cv), &s->hw_volume));
return 0;
}
static int sink_set_hw_volume(pa_sink *s) {
struct userdata *u = s->userdata;
char cv[PA_CVOLUME_SNPRINT_MAX];
unsigned vol;
vol = (s->hw_volume.values[0]*100)/PA_VOLUME_NORM;
if (s->sample_spec.channels >= 2)
vol |= ((s->hw_volume.values[1]*100)/PA_VOLUME_NORM) << 8;
if (ioctl(u->fd, SOUND_MIXER_WRITE_PCM, &vol) < 0) {
pa_log_info(__FILE__": device doesn't support writing mixer settings: %s\n", strerror(errno));
s->set_hw_volume = NULL;
return -1;
}
pa_log_info(__FILE__": Wrote mixer settings: %s\n", pa_cvolume_snprint(cv, sizeof(cv), &s->hw_volume));
return 0;
}
int pa__init(pa_core *c, pa_module*m) {
struct audio_buf_info info;
struct userdata *u = NULL;
@ -332,7 +370,7 @@ int pa__init(pa_core *c, pa_module*m) {
}
if (mode != O_WRONLY) {
u->source = pa_source_new(c, PA_TYPEID_OSS, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss);
u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL);
assert(u->source);
u->source->userdata = u;
u->source->notify = source_notify_cb;
@ -343,9 +381,11 @@ int pa__init(pa_core *c, pa_module*m) {
u->source = NULL;
if (mode != O_RDONLY) {
u->sink = pa_sink_new(c, PA_TYPEID_OSS, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss);
u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL);
assert(u->sink);
u->sink->get_latency = sink_get_latency_cb;
u->sink->get_hw_volume = sink_get_hw_volume;
u->sink->set_hw_volume = sink_set_hw_volume;
u->sink->userdata = u;
pa_sink_set_owner(u->sink, m);
u->sink->description = pa_sprintf_malloc("Open Sound System PCM on '%s'", p);
@ -384,6 +424,10 @@ int pa__init(pa_core *c, pa_module*m) {
read(u->fd, buf, u->sample_size);
}
/* Read mixer settings */
if (u->sink)
sink_get_hw_volume(u->sink);
return 0;
fail:

View file

@ -50,8 +50,6 @@ PA_MODULE_USAGE("sink_name=<name for the sink> file=<path of the FIFO> format=<s
#define DEFAULT_FIFO_NAME "/tmp/music.output"
#define DEFAULT_SINK_NAME "fifo_output"
#define PA_TYPEID_PIPE PA_TYPEID_MAKE('P', 'I', 'P', 'E')
struct userdata {
pa_core *core;
@ -177,7 +175,7 @@ int pa__init(pa_core *c, pa_module*m) {
u->module = m;
m->userdata = u;
if (!(u->sink = pa_sink_new(c, PA_TYPEID_PIPE, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) {
if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) {
pa_log(__FILE__": failed to create sink.\n");
goto fail;
}

View file

@ -50,8 +50,6 @@ PA_MODULE_USAGE("source_name=<name for the source> file=<path of the FIFO> forma
#define DEFAULT_FIFO_NAME "/tmp/music.input"
#define DEFAULT_SOURCE_NAME "fifo_input"
#define PA_TYPEID_PIPE PA_TYPEID_MAKE('P', 'I', 'P', 'E')
struct userdata {
pa_core *core;
@ -154,7 +152,7 @@ int pa__init(pa_core *c, pa_module*m) {
u->filename = pa_xstrdup(p);
u->core = c;
if (!(u->source = pa_source_new(c, PA_TYPEID_PIPE, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss))) {
if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL))) {
pa_log(__FILE__": failed to create source.\n");
goto fail;
}

View file

@ -146,7 +146,7 @@
#else
#include "module-esound-protocol-unix-symdef.h"
#endif
PA_MODULE_DESCRIPTION("EsounD protocol "SOCKET_DESCRIPTION)
PA_MODULE_DESCRIPTION("ESOUND protocol "SOCKET_DESCRIPTION)
PA_MODULE_USAGE("sink=<sink to connect to> source=<source to connect to> public=<don't check for cookies?> cookie=<path to cookie file> "SOCKET_USAGE)
#else
#error "Broken build system"

View file

@ -40,8 +40,6 @@ PA_MODULE_DESCRIPTION("Sine wave generator")
PA_MODULE_USAGE("sink=<sink to connect to> frequency=<frequency in Hz>")
PA_MODULE_VERSION(PACKAGE_VERSION)
#define PA_TYPEID_SINE PA_TYPEID_MAKE('S', 'I', 'N', 'E')
struct userdata {
pa_core *core;
pa_module *module;
@ -142,7 +140,7 @@ int pa__init(pa_core *c, pa_module*m) {
calc_sine(u->memblock->data, u->memblock->length, frequency);
snprintf(t, sizeof(t), "Sine Generator at %u Hz", frequency);
if (!(u->sink_input = pa_sink_input_new(sink, PA_TYPEID_SINE, t, &ss, 0, -1)))
if (!(u->sink_input = pa_sink_input_new(sink, __FILE__, t, &ss, NULL, 0, -1)))
goto fail;
u->sink_input->peek = sink_input_peek;

View file

@ -1,4 +1,4 @@
/* $Id: module-oss.c 333 2005-01-08 21:36:53Z lennart $ */
/* $Id$ */
/***
This file is part of polypaudio.

View file

@ -59,8 +59,6 @@ PA_MODULE_USAGE("server=<address> source=<remote source name> cookie=<filename>
PA_MODULE_AUTHOR("Lennart Poettering")
PA_MODULE_VERSION(PACKAGE_VERSION)
#define PA_TYPEID_TUNNEL PA_TYPEID_MAKE('T', 'U', 'N', 'L')
#define DEFAULT_SINK_NAME "tunnel"
#define DEFAULT_SOURCE_NAME "tunnel"
@ -625,7 +623,7 @@ int pa__init(pa_core *c, pa_module*m) {
pa_socket_client_set_callback(u->client, on_connection, u);
#ifdef TUNNEL_SINK
if (!(u->sink = pa_sink_new(c, PA_TYPEID_TUNNEL, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) {
if (!(u->sink = pa_sink_new(c, __FILE__, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss, NULL))) {
pa_log(__FILE__": failed to create sink.\n");
goto fail;
}
@ -637,7 +635,7 @@ int pa__init(pa_core *c, pa_module*m) {
pa_sink_set_owner(u->sink, m);
#else
if (!(u->source = pa_source_new(c, PA_TYPEID_TUNNEL, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss))) {
if (!(u->source = pa_source_new(c, __FILE__, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss, NULL))) {
pa_log(__FILE__": failed to create source.\n");
goto fail;
}

View file

@ -1,4 +1,4 @@
/* $Id: module-waveout.c 333 2005-01-08 21:36:53Z lennart $ */
/* $Id$ */
/***
This file is part of polypaudio.

View file

@ -66,6 +66,7 @@ static const char* const valid_modargs[] = {
static int ring_bell(struct userdata *u, int percent) {
pa_sink *s;
pa_cvolume cv;
assert(u);
if (!(s = pa_namereg_get(u->core, u->sink_name, PA_NAMEREG_SINK, 1))) {
@ -73,7 +74,7 @@ static int ring_bell(struct userdata *u, int percent) {
return -1;
}
pa_scache_play_item(u->core, u->scache_item, s, percent*2);
pa_scache_play_item(u->core, u->scache_item, s, pa_cvolume_set(&cv, PA_CHANNELS_MAX, percent*PA_VOLUME_NORM/100));
return 0;
}

View file

@ -38,7 +38,7 @@
#include "util.h"
struct namereg_entry {
pa_namereg_type type;
pa_namereg_type_t type;
char *name;
void *data;
};
@ -51,7 +51,7 @@ void pa_namereg_free(pa_core *c) {
pa_hashmap_free(c->namereg, NULL, NULL);
}
const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type type, void *data, int fail) {
const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, int fail) {
struct namereg_entry *e;
char *n = NULL;
int r;
@ -110,7 +110,7 @@ void pa_namereg_unregister(pa_core *c, const char *name) {
pa_xfree(e);
}
void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type type, int autoload) {
void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, int autoload) {
struct namereg_entry *e;
uint32_t idx;
assert(c);
@ -152,7 +152,7 @@ void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type type, int aut
return NULL;
}
void pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type type) {
void pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type) {
char **s;
assert(c && (type == PA_NAMEREG_SINK || type == PA_NAMEREG_SOURCE));

View file

@ -28,14 +28,14 @@ typedef enum pa_namereg_type {
PA_NAMEREG_SINK,
PA_NAMEREG_SOURCE,
PA_NAMEREG_SAMPLE
} pa_namereg_type ;
} pa_namereg_type_t;
void pa_namereg_free(pa_core *c);
const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type type, void *data, int fail);
const char *pa_namereg_register(pa_core *c, const char *name, pa_namereg_type_t type, void *data, int fail);
void pa_namereg_unregister(pa_core *c, const char *name);
void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type type, int autoload);
void pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type type);
void* pa_namereg_get(pa_core *c, const char *name, pa_namereg_type_t type, int autoload);
void pa_namereg_set_default(pa_core*c, const char *name, pa_namereg_type_t type);
const char *pa_namereg_get_default_sink_name(pa_core *c);
const char *pa_namereg_get_default_source_name(pa_core *c);

View file

@ -51,6 +51,7 @@ enum {
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,
@ -68,15 +69,19 @@ enum {
PA_COMMAND_GET_SAMPLE_INFO_LIST,
PA_COMMAND_SUBSCRIBE,
PA_COMMAND_SUBSCRIBE_EVENT,
PA_COMMAND_SET_SINK_VOLUME,
PA_COMMAND_SET_SINK_INPUT_VOLUME,
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,

View file

@ -48,7 +48,7 @@ int main(PA_GCC_UNUSED int argc, char*argv[]) {
int error;
/* Create a new playback stream */
if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, PA_VOLUME_NORM, &error))) {
if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_PLAYBACK, NULL, "playback", &ss, NULL, &error))) {
fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
goto finish;
}

View file

@ -162,16 +162,17 @@ static void context_state_callback(pa_context *c, void *userdata) {
if (verbose)
fprintf(stderr, "Connection established.\n");
stream = pa_stream_new(c, stream_name, &sample_spec);
stream = pa_stream_new(c, stream_name, &sample_spec, NULL);
assert(stream);
pa_stream_set_state_callback(stream, stream_state_callback, NULL);
pa_stream_set_write_callback(stream, stream_write_callback, NULL);
pa_stream_set_read_callback(stream, stream_read_callback, NULL);
if (mode == PLAYBACK)
pa_stream_connect_playback(stream, device, NULL, 0, volume);
else
if (mode == PLAYBACK) {
pa_cvolume cv;
pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, PA_CHANNELS_MAX, volume));
} else
pa_stream_connect_record(stream, device, NULL, 0);
break;
@ -219,7 +220,7 @@ static void stream_drain_complete(pa_stream*s, int success, void *userdata) {
}
/* New data on STDIN **/
static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata) {
static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
size_t l, w = 0;
ssize_t r;
assert(a == mainloop_api && e && stdio_event == e);
@ -257,7 +258,7 @@ static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_even
}
/* Some data may be written to STDOUT */
static void stdout_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags f, void *userdata) {
static void stdout_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
ssize_t r;
assert(a == mainloop_api && e && stdio_event == e);

View file

@ -149,8 +149,8 @@ static void get_server_info_callback(pa_context *c, const pa_server_info *i, voi
}
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], tid[5];
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);
@ -168,31 +168,31 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_
printf("\n");
nl = 1;
pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec);
printf("*** Sink #%u ***\n"
"Name: %s\n"
"Type: %s\n"
"Driver: %s\n"
"Description: %s\n"
"Sample Specification: %s\n"
"Channel Map: %s\n"
"Owner Module: %u\n"
"Volume: 0x%03x (%0.2f dB)\n"
"Volume: %s\n"
"Monitor Source: %u\n"
"Latency: %0.0f usec\n",
i->index,
i->name,
pa_typeid_to_string(i->_typeid, tid, sizeof(tid)),
i->driver,
i->description,
s,
pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
i->owner_module,
i->volume, pa_volume_to_dB(i->volume),
pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
i->monitor_source,
(double) i->latency);
}
static void get_source_info_callback(pa_context *c, const pa_source_info *i, int is_last, void *userdata) {
char s[PA_SAMPLE_SPEC_SNPRINT_MAX], t[32], tid[5];
char s[PA_SAMPLE_SPEC_SNPRINT_MAX], t[32], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
if (is_last < 0) {
fprintf(stderr, "Failed to get source information: %s\n", pa_strerror(pa_context_errno(c)));
@ -213,21 +213,21 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int
snprintf(t, sizeof(t), "%u", i->monitor_of_sink);
pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec);
printf("*** Source #%u ***\n"
"Name: %s\n"
"Type: %s\n"
"Driver: %s\n"
"Description: %s\n"
"Sample Specification: %s\n"
"Channel Map: %s\n"
"Owner Module: %u\n"
"Monitor of Sink: %s\n"
"Latency: %0.0f usec\n",
i->index,
pa_typeid_to_string(i->_typeid, tid, sizeof(tid)),
i->driver,
i->name,
i->description,
s,
pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
i->owner_module,
i->monitor_of_sink != PA_INVALID_INDEX ? t : "no",
(double) i->latency);
@ -269,7 +269,7 @@ static void get_module_info_callback(pa_context *c, const pa_module_info *i, int
}
static void get_client_info_callback(pa_context *c, const pa_client_info *i, int is_last, void *userdata) {
char t[32], tid[5];
char t[32];
if (is_last < 0) {
fprintf(stderr, "Failed to get client information: %s\n", pa_strerror(pa_context_errno(c)));
@ -292,16 +292,16 @@ static void get_client_info_callback(pa_context *c, const pa_client_info *i, int
printf("*** Client #%u ***\n"
"Name: %s\n"
"Type: %s\n"
"Driver: %s\n"
"Owner Module: %s\n",
i->index,
i->name,
pa_typeid_to_string(i->_typeid, tid, sizeof(tid)),
i->driver,
i->owner_module != PA_INVALID_INDEX ? t : "n/a");
}
static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info *i, int is_last, void *userdata) {
char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], tid[5];
char t[32], k[32], 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 input information: %s\n", pa_strerror(pa_context_errno(c)));
@ -320,29 +320,30 @@ static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info
printf("\n");
nl = 1;
pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec);
snprintf(t, sizeof(t), "%u", i->owner_module);
snprintf(k, sizeof(k), "%u", i->client);
printf("*** Sink Input #%u ***\n"
"Name: %s\n"
"Type: %s\n"
"Driver: %s\n"
"Owner Module: %s\n"
"Client: %s\n"
"Sink: %u\n"
"Sample Specification: %s\n"
"Volume: 0x%03x (%0.2f dB)\n"
"Channel Map: %s\n"
"Volume: %s\n"
"Buffer Latency: %0.0f usec\n"
"Sink Latency: %0.0f usec\n"
"Resample method: %s\n",
i->index,
i->name,
pa_typeid_to_string(i->_typeid, tid, sizeof(tid)),
i->driver,
i->owner_module != PA_INVALID_INDEX ? t : "n/a",
i->client != PA_INVALID_INDEX ? k : "n/a",
i->sink,
s,
i->volume, pa_volume_to_dB(i->volume),
pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
(double) i->buffer_usec,
(double) i->sink_usec,
i->resample_method ? i->resample_method : "n/a");
@ -350,7 +351,7 @@ static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info
static void get_source_output_info_callback(pa_context *c, const pa_source_output_info *i, int is_last, void *userdata) {
char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], tid[5];
char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
if (is_last < 0) {
fprintf(stderr, "Failed to get source output information: %s\n", pa_strerror(pa_context_errno(c)));
@ -369,34 +370,36 @@ static void get_source_output_info_callback(pa_context *c, const pa_source_outpu
printf("\n");
nl = 1;
pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec);
snprintf(t, sizeof(t), "%u", i->owner_module);
snprintf(k, sizeof(k), "%u", i->client);
printf("*** Source Output #%u ***\n"
"Name: %s\n"
"Type: %s\n"
"Driver: %s\n"
"Owner Module: %s\n"
"Client: %s\n"
"Source: %u\n"
"Sample Specification: %s\n"
"Channel Map: %s\n"
"Buffer Latency: %0.0f usec\n"
"Source Latency: %0.0f usec\n"
"Resample method: %s\n",
i->index,
i->name,
pa_typeid_to_string(i->_typeid, tid, sizeof(tid)),
i->driver,
i->owner_module != PA_INVALID_INDEX ? t : "n/a",
i->client != PA_INVALID_INDEX ? k : "n/a",
i->source,
s,
pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
(double) i->buffer_usec,
(double) i->source_usec,
i->resample_method ? i->resample_method : "n/a");
}
static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int is_last, void *userdata) {
char t[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX];
char t[32], 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 sample information: %s\n", pa_strerror(pa_context_errno(c)));
@ -415,21 +418,23 @@ static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int
printf("\n");
nl = 1;
pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec);
pa_bytes_snprint(t, sizeof(t), i->bytes);
printf("*** Sample #%u ***\n"
"Name: %s\n"
"Volume: 0x%03x (%0.2f dB)\n"
"Volume: %s\n"
"Sample Specification: %s\n"
"Channel Map: %s\n"
"Duration: %0.1fs\n"
"Size: %s\n"
"Lazy: %s\n"
"Filename: %s\n",
i->index,
i->name,
i->volume, pa_volume_to_dB(i->volume),
pa_sample_spec_valid(&i->sample_spec) ? s : "n/a",
pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
pa_sample_spec_valid(&i->sample_spec) ? pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec) : "n/a",
pa_sample_spec_valid(&i->sample_spec) ? pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map) : "n/a",
(double) i->duration/1000000,
t,
i->lazy ? "yes" : "no",
@ -547,7 +552,7 @@ static void context_state_callback(pa_context *c, void *userdata) {
break;
case UPLOAD_SAMPLE:
sample_stream = pa_stream_new(c, sample_name, &sample_spec);
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);

View file

@ -155,21 +155,23 @@ static void context_state_callback(pa_context *c, void *userdata) {
case PA_CONTEXT_SETTING_NAME:
break;
case PA_CONTEXT_READY:
case PA_CONTEXT_READY: {
pa_cvolume cv;
assert(c && !stream);
if (verbose)
fprintf(stderr, "Connection established.\n");
stream = pa_stream_new(c, stream_name, &sample_spec);
stream = pa_stream_new(c, stream_name, &sample_spec, NULL);
assert(stream);
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, volume);
pa_stream_connect_playback(stream, device, NULL, 0, pa_cvolume_set(&cv, PA_CHANNELS_MAX, volume));
break;
}
case PA_CONTEXT_TERMINATED:
quit(0);

View file

@ -67,7 +67,7 @@ int main(PA_GCC_UNUSED int argc, char*argv[]) {
int error;
/* Create the recording stream */
if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_RECORD, NULL, "record", &ss, NULL, 0, &error))) {
if (!(s = pa_simple_new(NULL, argv[0], PA_STREAM_RECORD, NULL, "record", &ss, NULL, &error))) {
fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
goto finish;
}

View file

@ -29,10 +29,10 @@ typedef enum pa_parsed_address_type {
PA_PARSED_ADDRESS_TCP4,
PA_PARSED_ADDRESS_TCP6,
PA_PARSED_ADDRESS_TCP_AUTO
} pa_parsed_address_type;
} pa_parsed_address_type_t;
typedef struct pa_parsed_address {
pa_parsed_address_type type;
pa_parsed_address_type_t type;
char *path_or_host;
uint16_t port;
} pa_parsed_address;

View file

@ -33,8 +33,6 @@
#include "xmalloc.h"
#include "gccmacro.h"
#define PA_TYPEID_MEMCHUNK PA_TYPEID_MAKE('M', 'C', 'N', 'K')
static void sink_input_kill(pa_sink_input *i) {
pa_memchunk *c;
assert(i && i->userdata);
@ -45,7 +43,6 @@ static void sink_input_kill(pa_sink_input *i) {
pa_memblock_unref(c->memblock);
pa_xfree(c);
}
static int sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) {
@ -82,24 +79,35 @@ static void sink_input_drop(pa_sink_input *i, const pa_memchunk*chunk, size_t le
pa_mainloop_api_once(i->sink->core->mainloop, si_kill, i);
}
int pa_play_memchunk(pa_sink *sink, const char *name, const pa_sample_spec *ss, const pa_memchunk *chunk, pa_volume_t volume) {
int pa_play_memchunk(
pa_sink *sink,
const char *name,
const pa_sample_spec *ss,
const pa_channel_map *map,
const pa_memchunk *chunk,
pa_cvolume *cvolume) {
pa_sink_input *si;
pa_memchunk *nchunk;
assert(sink && chunk);
assert(sink);
assert(ss);
assert(chunk);
if (volume <= 0)
if (cvolume && pa_cvolume_is_muted(cvolume))
return 0;
if (!(si = pa_sink_input_new(sink, PA_TYPEID_MEMCHUNK, name, ss, 0, -1)))
if (!(si = pa_sink_input_new(sink, name, __FILE__, ss, map, 0, PA_RESAMPLER_INVALID)))
return -1;
si->volume = volume;
if (cvolume)
si->volume = *cvolume;
si->peek = sink_input_peek;
si->drop = sink_input_drop;
si->kill = sink_input_kill;
si->userdata = nchunk = pa_xmalloc(sizeof(pa_memchunk));
si->userdata = nchunk = pa_xnew(pa_memchunk, 1);
*nchunk = *chunk;
pa_memblock_ref(chunk->memblock);

View file

@ -25,6 +25,12 @@
#include "sink.h"
#include "memchunk.h"
int pa_play_memchunk(pa_sink *sink, const char *name, const pa_sample_spec *ss, const pa_memchunk *chunk, pa_volume_t volume);
int pa_play_memchunk(
pa_sink *sink,
const char *name,
const pa_sample_spec *ss,
const pa_channel_map *map,
const pa_memchunk *chunk,
pa_cvolume *cvolume);
#endif

View file

@ -1,4 +1,4 @@
/* $Id: mainloop.c 302 2004-11-21 17:02:25Z lennart $ */
/* $Id$ */
/***
Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc.

View file

@ -1,4 +1,4 @@
/* $Id: mainloop.c 302 2004-11-21 17:02:25Z lennart $ */
/* $Id$ */
/***
Compatibility definitions for System V `poll' interface.

View file

@ -187,7 +187,7 @@ void pa_context_unref(pa_context *c) {
context_free(c);
}
void pa_context_set_state(pa_context *c, pa_context_state st) {
void pa_context_set_state(pa_context *c, pa_context_state_t st) {
assert(c);
if (c->state == st)
@ -644,7 +644,7 @@ void pa_context_disconnect(pa_context *c) {
pa_context_set_state(c, PA_CONTEXT_TERMINATED);
}
pa_context_state pa_context_get_state(pa_context *c) {
pa_context_state_t pa_context_get_state(pa_context *c) {
assert(c && c->ref >= 1);
return c->state;
}

View file

@ -75,7 +75,7 @@ int pa_context_errno(pa_context *c);
int pa_context_is_pending(pa_context *c);
/** Return the current context status */
pa_context_state pa_context_get_state(pa_context *c);
pa_context_state_t pa_context_get_state(pa_context *c);
/** Connect the context to the specified server. If server is NULL,
connect to the default server. This routine may but will not always

View file

@ -43,7 +43,7 @@ typedef enum pa_context_state {
PA_CONTEXT_READY, /**< The connection is established, the context is ready to execute operations */
PA_CONTEXT_FAILED, /**< The connection failed or was disconnected */
PA_CONTEXT_TERMINATED /**< The connection was terminated cleanly */
} pa_context_state;
} pa_context_state_t;
/** The state of a stream */
typedef enum pa_stream_state {
@ -52,14 +52,14 @@ typedef enum pa_stream_state {
PA_STREAM_READY, /**< The stream is established, you may pass audio data to it now */
PA_STREAM_FAILED, /**< An error occured that made the stream invalid */
PA_STREAM_TERMINATED /**< The stream has been terminated cleanly */
} pa_stream_state;
} pa_stream_state_t;
/** The state of an operation */
typedef enum pa_operation_state {
PA_OPERATION_RUNNING, /**< The operation is still running */
PA_OPERATION_DONE, /**< The operation has been completed */
PA_OPERATION_CANCELED /**< The operation has been canceled */
} pa_operation_state;
} pa_operation_state_t;
/** An invalid index */
#define PA_INVALID_INDEX ((uint32_t) -1)
@ -70,7 +70,7 @@ typedef enum pa_stream_direction {
PA_STREAM_PLAYBACK, /**< Playback stream */
PA_STREAM_RECORD, /**< Record stream */
PA_STREAM_UPLOAD /**< Sample upload stream */
} pa_stream_direction;
} pa_stream_direction_t;
/** Some special flags for stream connections. \since 0.6 */
typedef enum pa_stream_flags {
@ -90,7 +90,7 @@ typedef enum pa_stream_flags {
* information. This is
* especially useful on long latency
* network connections. */
} pa_stream_flags;
} pa_stream_flags_t;
/** Playback and record buffer metrics */
typedef struct pa_buffer_attr {
@ -133,7 +133,7 @@ typedef enum pa_subscription_mask {
PA_SUBSCRIPTION_MASK_SAMPLE_CACHE = 64, /**< Sample cache events */
PA_SUBSCRIPTION_MASK_SERVER = 128, /**< Other global server changes. \since 0.4 */
PA_SUBSCRIPTION_MASK_AUTOLOAD = 256 /**< Autoload table events. \since 0.5 */
} pa_subscription_mask;
} pa_subscription_mask_t;
/** Subscription event types, as used by pa_context_subscribe() */
typedef enum pa_subscription_event_type {
@ -152,7 +152,7 @@ typedef enum pa_subscription_event_type {
PA_SUBSCRIPTION_EVENT_CHANGE = 16, /**< A property of the object was modified */
PA_SUBSCRIPTION_EVENT_REMOVE = 32, /**< An object was removed */
PA_SUBSCRIPTION_EVENT_TYPE_MASK = 16+32 /**< A mask to extract the event operation from an event value */
} pa_subscription_event_type;
} pa_subscription_event_type_t;
/** Return one if an event type t matches an event mask bitfield */
#define pa_subscription_match_flags(m, t) (!!((m) & (1 << ((t) & PA_SUBSCRIPTION_EVENT_FACILITY_MASK))))

View file

@ -55,12 +55,12 @@ struct pa_context {
uint32_t ctag;
uint32_t error;
pa_context_state state;
pa_context_state_t state;
void (*state_callback)(pa_context*c, void *userdata);
void *state_userdata;
void (*subscribe_callback)(pa_context *c, pa_subscription_event_type t, uint32_t idx, void *userdata);
void (*subscribe_callback)(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata);
void *subscribe_userdata;
pa_memblock_stat *memblock_stat;
@ -86,15 +86,16 @@ struct pa_stream {
char *name;
pa_buffer_attr buffer_attr;
pa_sample_spec sample_spec;
pa_channel_map channel_map;
uint32_t channel;
int channel_valid;
uint32_t device_index;
pa_stream_direction direction;
pa_stream_direction_t direction;
uint32_t requested_bytes;
uint64_t counter;
pa_usec_t previous_time;
pa_usec_t previous_ipol_time;
pa_stream_state state;
pa_stream_state_t state;
pa_mcalign *mcalign;
int interpolate;
@ -123,7 +124,7 @@ struct pa_operation {
pa_stream *stream;
PA_LLIST_FIELDS(pa_operation);
pa_operation_state state;
pa_operation_state_t state;
void *userdata;
pa_operation_callback callback;
};
@ -141,11 +142,11 @@ void pa_context_simple_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t
void pa_stream_simple_ack_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
void pa_context_fail(pa_context *c, int error);
void pa_context_set_state(pa_context *c, pa_context_state st);
void pa_context_set_state(pa_context *c, pa_context_state_t st);
int pa_context_handle_error(pa_context *c, uint32_t command, pa_tagstruct *t);
pa_operation* pa_context_send_simple_command(pa_context *c, uint32_t command, void (*internal_callback)(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata), void (*cb)(void), void *userdata);
void pa_stream_set_state(pa_stream *s, pa_stream_state st);
void pa_stream_set_state(pa_stream *s, pa_stream_state_t st);
void pa_stream_trash_ipol(pa_stream *s);

View file

@ -128,12 +128,13 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, P
pa_tagstruct_gets(t, &i.name) < 0 ||
pa_tagstruct_gets(t, &i.description) < 0 ||
pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
pa_tagstruct_getu32(t, &i.volume) < 0 ||
pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
pa_tagstruct_getu32(t, &i.monitor_source) < 0 ||
pa_tagstruct_gets(t, &i.monitor_source_name) < 0 ||
pa_tagstruct_get_usec(t, &i.latency) < 0 ||
pa_tagstruct_getu32(t, &i._typeid) < 0) {
pa_tagstruct_gets(t, &i.driver) < 0) {
pa_context_fail(o->context, PA_ERROR_PROTOCOL);
goto finish;
@ -223,11 +224,12 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command,
pa_tagstruct_gets(t, &i.name) < 0 ||
pa_tagstruct_gets(t, &i.description) < 0 ||
pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
pa_tagstruct_getu32(t, &i.monitor_of_sink) < 0 ||
pa_tagstruct_gets(t, &i.monitor_of_sink_name) < 0 ||
pa_tagstruct_get_usec(t, &i.latency) < 0 ||
pa_tagstruct_getu32(t, &i._typeid) < 0) {
pa_tagstruct_gets(t, &i.driver) < 0) {
pa_context_fail(o->context, PA_ERROR_PROTOCOL);
goto finish;
@ -316,7 +318,7 @@ static void context_get_client_info_callback(pa_pdispatch *pd, uint32_t command,
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_getu32(t, &i._typeid) < 0 ) {
pa_tagstruct_gets(t, &i.driver) < 0 ) {
pa_context_fail(o->context, PA_ERROR_PROTOCOL);
goto finish;
}
@ -452,11 +454,12 @@ static void context_get_sink_input_info_callback(pa_pdispatch *pd, uint32_t comm
pa_tagstruct_getu32(t, &i.client) < 0 ||
pa_tagstruct_getu32(t, &i.sink) < 0 ||
pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
pa_tagstruct_getu32(t, &i.volume) < 0 ||
pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 ||
pa_tagstruct_get_usec(t, &i.sink_usec) < 0 ||
pa_tagstruct_gets(t, &i.resample_method) < 0 ||
pa_tagstruct_getu32(t, &i._typeid) < 0) {
pa_tagstruct_gets(t, &i.driver) < 0) {
pa_context_fail(o->context, PA_ERROR_PROTOCOL);
goto finish;
@ -526,10 +529,11 @@ static void context_get_source_output_info_callback(pa_pdispatch *pd, uint32_t c
pa_tagstruct_getu32(t, &i.client) < 0 ||
pa_tagstruct_getu32(t, &i.source) < 0 ||
pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
pa_tagstruct_get_usec(t, &i.buffer_usec) < 0 ||
pa_tagstruct_get_usec(t, &i.source_usec) < 0 ||
pa_tagstruct_gets(t, &i.resample_method) < 0 ||
pa_tagstruct_getu32(t, &i._typeid) < 0) {
pa_tagstruct_gets(t, &i.driver) < 0) {
pa_context_fail(o->context, PA_ERROR_PROTOCOL);
goto finish;
@ -662,9 +666,10 @@ static void context_get_sample_info_callback(pa_pdispatch *pd, uint32_t command,
if (pa_tagstruct_getu32(t, &i.index) < 0 ||
pa_tagstruct_gets(t, &i.name) < 0 ||
pa_tagstruct_getu32(t, &i.volume) < 0 ||
pa_tagstruct_get_cvolume(t, &i.volume) < 0 ||
pa_tagstruct_get_usec(t, &i.duration) < 0 ||
pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
pa_tagstruct_get_channel_map(t, &i.channel_map) < 0 ||
pa_tagstruct_getu32(t, &i.bytes) < 0 ||
pa_tagstruct_get_boolean(t, &i.lazy) < 0 ||
pa_tagstruct_gets(t, &i.filename) < 0) {
@ -861,7 +866,7 @@ finish:
pa_operation_unref(o);
}
pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type type, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata) {
pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type_t type, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata) {
pa_tagstruct *t;
pa_operation *o;
uint32_t tag;
@ -933,8 +938,7 @@ finish:
pa_operation_unref(o);
}
pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type type, const char *module, const char*argument, void (*cb)(pa_context *c, int success, void *userdata), void* userdata) {
pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type_t type, const char *module, const char*argument, void (*cb)(pa_context *c, int success, void *userdata), void* userdata) {
pa_operation *o;
pa_tagstruct *t;
uint32_t tag;
@ -957,7 +961,7 @@ pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autolo
return pa_operation_ref(o);
}
pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type type, void (*cb)(pa_context *c, int success, void *userdata), void* userdata) {
pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type_t type, void (*cb)(pa_context *c, int success, void *userdata), void* userdata) {
pa_operation *o;
pa_tagstruct *t;
uint32_t tag;

View file

@ -27,7 +27,8 @@
#include <polyp/polyplib-operation.h>
#include <polyp/polyplib-context.h>
#include <polyp/cdecl.h>
#include <polyp/typeid.h>
#include <polyp/channelmap.h>
#include <polyp/volume.h>
/** \file
*
@ -52,13 +53,14 @@ typedef struct pa_sink_info {
const char *name; /**< Name 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_sample_spec sample_spec; /**< Sample spec of this sink */
pa_channel_map channel_map; /**< Channel map \since 0.9 */
uint32_t owner_module; /**< Index of the owning module of this sink, or PA_INVALID_INDEX */
pa_volume_t volume; /**< Volume of the sink */
pa_cvolume volume; /**< Volume of the sink */
uint32_t monitor_source; /**< Index of the monitor source connected to this sink */
const char *monitor_source_name; /**< The name of the monitor source */
pa_usec_t latency; /**< Length of filled playback buffer of this sink */
pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */
const char *driver; /**< Driver name. \since 0.9 */
} pa_sink_info;
/** Get information about a sink by its name */
@ -75,12 +77,13 @@ 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 */
pa_sample_spec sample_spec; /**< Sample spec of this source */
pa_sample_spec sample_spec; /**< Sample spec of this source */
pa_channel_map channel_map; /**< Channel map \since 0.9 */
uint32_t owner_module; /**< Owning module index, or PA_INVALID_INDEX */
uint32_t monitor_of_sink; /**< If this is a monitor source the index of the owning sink, otherwise PA_INVALID_INDEX */
const char *monitor_of_sink_name; /**< Name of the owning sink, or PA_INVALID_INDEX */
pa_usec_t latency; /**< Length of filled record buffer of this source. \since 0.5 */
pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */
const char *driver; /**< Driver name \since 0.9 */
} pa_source_info;
/** Get information about a source by its name */
@ -98,7 +101,7 @@ typedef struct pa_server_info {
const char *host_name; /**< Host name the daemon is running on */
const char *server_version; /**< Version string of the daemon */
const char *server_name; /**< Server package name (usually "polypaudio") */
pa_sample_spec sample_spec; /**< Default sample specification */
pa_sample_spec sample_spec; /**< Default sample specification */
const char *default_sink_name; /**< Name of default sink. \since 0.4 */
const char *default_source_name; /**< Name of default sink. \since 0.4*/
uint32_t cookie; /**< A random cookie for identifying this instance of polypaudio. \since 0.8 */
@ -127,7 +130,7 @@ typedef struct pa_client_info {
uint32_t index; /**< Index of this client */
const char *name; /**< Name of this client */
uint32_t owner_module; /**< Index of the owning module, or PA_INVALID_INDEX */
pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */
const char *driver; /**< Driver name \since 0.9 */
} pa_client_info;
/** Get information about a client by its index */
@ -143,12 +146,13 @@ typedef struct pa_sink_input_info {
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 sink; /**< Index of the connected sink */
pa_sample_spec sample_spec; /**< The sample specification of the sink input */
pa_volume_t volume; /**< The volume of this sink input */
pa_sample_spec sample_spec; /**< The sample specification of the sink input */
pa_channel_map channel_map; /**< Channel map */
pa_cvolume volume; /**< The volume of this sink input */
pa_usec_t buffer_usec; /**< Latency due to buffering in sink input, see pa_latency_info for details */
pa_usec_t sink_usec; /**< Latency of the sink device, see pa_latency_info for details */
const char *resample_method; /**< Thre resampling method used by this sink input. \since 0.7 */
pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */
const char *driver; /**< Driver name \since 0.9 */
} pa_sink_input_info;
/** Get some information about a sink input by its index */
@ -164,11 +168,12 @@ typedef struct pa_source_output_info {
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_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 */
pa_usec_t source_usec; /**< Latency of the source device, see pa_latency_info for details. \since 0.5 */
const char *resample_method; /**< Thre resampling method used by this source output. \since 0.7 */
pa_typeid_t _typeid; /**< Implementation type. \since 0.8 */
const char *driver; /**< Driver name \since 0.9 */
} pa_source_output_info;
/** Get information about a source output by its index */
@ -202,8 +207,9 @@ pa_operation* pa_context_stat(pa_context *c, void (*cb)(pa_context *c, const pa_
typedef struct pa_sample_info {
uint32_t index; /**< Index of this entry */
const char *name; /**< Name of this entry */
pa_volume_t volume; /**< Default volume of this entry */
pa_sample_spec sample_spec; /**< Sample specification of the sampel */
pa_cvolume volume; /**< Default volume of this entry */
pa_sample_spec sample_spec; /**< Sample specification of the sample */
pa_channel_map channel_map; /**< The channel map */
pa_usec_t duration; /**< Duration of this entry */
uint32_t bytes; /**< Length of this sample in bytes. \since 0.4 */
int lazy; /**< Non-zero when this is a lazy cache entry. \since 0.5 */
@ -238,19 +244,19 @@ pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, void (*cb)(p
typedef enum pa_autoload_type {
PA_AUTOLOAD_SINK = 0,
PA_AUTOLOAD_SOURCE = 1
} pa_autoload_type;
} pa_autoload_type_t;
/** Stores information about autoload entries. \since 0.5 */
typedef struct pa_autoload_info {
uint32_t index; /**< Index of this autoload entry */
const char *name; /**< Name of the sink or source */
pa_autoload_type type; /**< Type of the autoload entry */
pa_autoload_type_t type; /**< Type of the autoload entry */
const char *module; /**< Module name to load */
const char *argument; /**< Argument string for module */
} pa_autoload_info;
/** Get info about a specific autoload entry. \since 0.6 */
pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type type, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata);
pa_operation* pa_context_get_autoload_info_by_name(pa_context *c, const char *name, pa_autoload_type_t type, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata);
/** Get info about a specific autoload entry. \since 0.6 */
pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata);
@ -259,10 +265,10 @@ pa_operation* pa_context_get_autoload_info_by_index(pa_context *c, uint32_t idx,
pa_operation* pa_context_get_autoload_info_list(pa_context *c, void (*cb)(pa_context *c, const pa_autoload_info *i, int is_last, void *userdata), void *userdata);
/** Add a new autoload entry. \since 0.5 */
pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type type, const char *module, const char*argument, void (*cb)(pa_context *c, int idx, void *userdata), void* userdata);
pa_operation* pa_context_add_autoload(pa_context *c, const char *name, pa_autoload_type_t type, const char *module, const char*argument, void (*cb)(pa_context *c, int idx, void *userdata), void* userdata);
/** Remove an autoload entry. \since 0.6 */
pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type type, void (*cb)(pa_context *c, int success, void *userdata), void* userdata);
pa_operation* pa_context_remove_autoload_by_name(pa_context *c, const char *name, pa_autoload_type_t type, void (*cb)(pa_context *c, int success, void *userdata), void* userdata);
/** Remove an autoload entry. \since 0.6 */
pa_operation* pa_context_remove_autoload_by_index(pa_context *c, uint32_t idx, void (*cb)(pa_context *c, int success, void *userdata), void* userdata);

View file

@ -62,7 +62,7 @@ void pa_operation_unref(pa_operation *o) {
}
}
static void operation_set_state(pa_operation *o, pa_operation_state st) {
static void operation_set_state(pa_operation *o, pa_operation_state_t st) {
assert(o && o->ref >= 1);
if (st == o->state)
@ -97,7 +97,7 @@ void pa_operation_done(pa_operation *o) {
operation_set_state(o, PA_OPERATION_DONE);
}
pa_operation_state pa_operation_get_state(pa_operation *o) {
pa_operation_state_t pa_operation_get_state(pa_operation *o) {
assert(o && o->ref >= 1);
return o->state;
}

View file

@ -44,7 +44,7 @@ void pa_operation_unref(pa_operation *o);
void pa_operation_cancel(pa_operation *o);
/** Return the current status of the operation */
pa_operation_state pa_operation_get_state(pa_operation *o);
pa_operation_state_t pa_operation_get_state(pa_operation *o);
PA_C_DECL_END

View file

@ -39,7 +39,7 @@ struct pa_simple {
pa_mainloop *mainloop;
pa_context *context;
pa_stream *stream;
pa_stream_direction direction;
pa_stream_direction_t direction;
int dead;
@ -51,8 +51,8 @@ struct pa_simple {
static void read_callback(pa_stream *s, const void*data, size_t length, void *userdata);
static int check_error(pa_simple *p, int *rerror) {
pa_context_state cst;
pa_stream_state sst;
pa_context_state_t cst;
pa_stream_state_t sst;
assert(p);
if ((cst = pa_context_get_state(p->context)) == PA_CONTEXT_FAILED)
@ -118,12 +118,11 @@ static int iterate(pa_simple *p, int block, int *rerror) {
pa_simple* pa_simple_new(
const char *server,
const char *name,
pa_stream_direction dir,
pa_stream_direction_t dir,
const char *dev,
const char *stream_name,
const pa_sample_spec *ss,
const pa_buffer_attr *attr,
pa_volume_t volume,
int *rerror) {
pa_simple *p;
@ -152,11 +151,11 @@ pa_simple* pa_simple_new(
goto fail;
}
if (!(p->stream = pa_stream_new(p->context, stream_name, ss)))
if (!(p->stream = pa_stream_new(p->context, stream_name, ss, NULL)))
goto fail;
if (dir == PA_STREAM_PLAYBACK)
pa_stream_connect_playback(p->stream, dev, attr, 0, volume);
pa_stream_connect_playback(p->stream, dev, attr, 0, NULL);
else
pa_stream_connect_record(p->stream, dev, attr, 0);

View file

@ -49,12 +49,11 @@ typedef struct pa_simple pa_simple;
pa_simple* pa_simple_new(
const char *server, /**< Server name, or NULL for default */
const char *name, /**< A descriptive name for this client (application name, ...) */
pa_stream_direction dir, /**< Open this stream for recording or playback? */
pa_stream_direction_t dir, /**< Open this stream for recording or playback? */
const char *dev, /**< Sink (resp. source) name, or NULL for default */
const char *stream_name, /**< A descriptive name for this client (application name, song title, ...) */
const pa_sample_spec *ss, /**< The sample type to use */
const pa_buffer_attr *attr, /**< Buffering attributes, or NULL for default */
pa_volume_t volume, /**< Initial volume. Only for playback streams. \since 0.5 */
int *error /**< A pointer where the error code is stored when the routine returns NULL. It is OK to pass NULL here. */
);

View file

@ -36,11 +36,18 @@
#define LATENCY_IPOL_INTERVAL_USEC (10000L)
pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss) {
pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map) {
pa_stream *s;
assert(c && ss);
assert(c);
assert(ss);
s = pa_xmalloc(sizeof(pa_stream));
if (!pa_sample_spec_valid(ss))
return NULL;
if (map && !pa_channel_map_valid(map))
return NULL;
s = pa_xnew(pa_stream, 1);
s->ref = 1;
s->context = c;
s->mainloop = c->mainloop;
@ -55,6 +62,12 @@ pa_stream *pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *
s->direction = PA_STREAM_NODIRECTION;
s->name = pa_xstrdup(name);
s->sample_spec = *ss;
if (map)
s->channel_map = *map;
else
pa_channel_map_init_auto(&s->channel_map, ss->channels);
s->channel = 0;
s->channel_valid = 0;
s->device_index = PA_INVALID_INDEX;
@ -108,7 +121,7 @@ pa_stream* pa_stream_ref(pa_stream *s) {
return s;
}
pa_stream_state pa_stream_get_state(pa_stream *s) {
pa_stream_state_t pa_stream_get_state(pa_stream *s) {
assert(s && s->ref >= 1);
return s->state;
}
@ -123,7 +136,7 @@ uint32_t pa_stream_get_index(pa_stream *s) {
return s->device_index;
}
void pa_stream_set_state(pa_stream *s, pa_stream_state st) {
void pa_stream_set_state(pa_stream *s, pa_stream_state_t st) {
assert(s && s->ref >= 1);
if (s->state == st)
@ -271,7 +284,7 @@ finish:
pa_stream_unref(s);
}
static void create_stream(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags flags, pa_volume_t volume) {
static void create_stream(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags_t flags, const pa_cvolume *volume) {
pa_tagstruct *t;
uint32_t tag;
assert(s && s->ref >= 1 && s->state == PA_STREAM_DISCONNECTED);
@ -308,15 +321,23 @@ static void create_stream(pa_stream *s, const char *dev, const pa_buffer_attr *a
pa_tagstruct_putu32(t, tag = s->context->ctag++);
pa_tagstruct_puts(t, s->name);
pa_tagstruct_put_sample_spec(t, &s->sample_spec);
pa_tagstruct_put_channel_map(t, &s->channel_map);
pa_tagstruct_putu32(t, PA_INVALID_INDEX);
pa_tagstruct_puts(t, dev);
pa_tagstruct_putu32(t, s->buffer_attr.maxlength);
pa_tagstruct_put_boolean(t, !!(flags & PA_STREAM_START_CORKED));
if (s->direction == PA_STREAM_PLAYBACK) {
pa_cvolume cv;
pa_tagstruct_putu32(t, s->buffer_attr.tlength);
pa_tagstruct_putu32(t, s->buffer_attr.prebuf);
pa_tagstruct_putu32(t, s->buffer_attr.minreq);
pa_tagstruct_putu32(t, volume);
if (!volume) {
pa_cvolume_reset(&cv, s->sample_spec.channels);
volume = &cv;
}
pa_tagstruct_put_cvolume(t, volume);
} else
pa_tagstruct_putu32(t, s->buffer_attr.fragsize);
@ -326,13 +347,13 @@ static void create_stream(pa_stream *s, const char *dev, const pa_buffer_attr *a
pa_stream_unref(s);
}
void pa_stream_connect_playback(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags flags, pa_volume_t volume) {
void pa_stream_connect_playback(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags_t flags, pa_cvolume *volume) {
assert(s && s->context->state == PA_CONTEXT_READY && s->ref >= 1);
s->direction = PA_STREAM_PLAYBACK;
create_stream(s, dev, attr, flags, volume);
}
void pa_stream_connect_record(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags flags) {
void pa_stream_connect_record(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags_t flags) {
assert(s && s->context->state == PA_CONTEXT_READY && s->ref >= 1);
s->direction = PA_STREAM_RECORD;
create_stream(s, dev, attr, flags, 0);

View file

@ -25,6 +25,8 @@
#include <sys/types.h>
#include <polyp/sample.h>
#include <polyp/channelmap.h>
#include <polyp/volume.h>
#include <polyp/polyplib-def.h>
#include <polyp/cdecl.h>
#include <polyp/polyplib-operation.h>
@ -39,7 +41,7 @@ PA_C_DECL_BEGIN
typedef struct pa_stream pa_stream;
/** Create a new, unconnected stream with the specified name and sample type */
pa_stream* pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss);
pa_stream* pa_stream_new(pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map);
/** Decrease the reference counter by one */
void pa_stream_unref(pa_stream *s);
@ -48,7 +50,7 @@ void pa_stream_unref(pa_stream *s);
pa_stream *pa_stream_ref(pa_stream *s);
/** Return the current state of the stream */
pa_stream_state pa_stream_get_state(pa_stream *p);
pa_stream_state_t pa_stream_get_state(pa_stream *p);
/** Return the context this stream is attached to */
pa_context* pa_stream_get_context(pa_stream *p);
@ -57,10 +59,19 @@ pa_context* pa_stream_get_context(pa_stream *p);
uint32_t pa_stream_get_index(pa_stream *s);
/** Connect the stream to a sink */
void pa_stream_connect_playback(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags flags, pa_volume_t volume);
void pa_stream_connect_playback(
pa_stream *s,
const char *dev,
const pa_buffer_attr *attr,
pa_stream_flags_t flags,
pa_cvolume *volume);
/** Connect the stream to a source */
void pa_stream_connect_record(pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags flags);
void pa_stream_connect_record(
pa_stream *s,
const char *dev,
const pa_buffer_attr *attr,
pa_stream_flags_t flags);
/** Disconnect a stream from a source/sink */
void pa_stream_disconnect(pa_stream *s);

View file

@ -33,7 +33,7 @@
void pa_command_subscribe_event(pa_pdispatch *pd, uint32_t command, PA_GCC_UNUSED uint32_t tag, pa_tagstruct *t, void *userdata) {
pa_context *c = userdata;
pa_subscription_event_type e;
pa_subscription_event_type_t e;
uint32_t index;
assert(pd && command == PA_COMMAND_SUBSCRIBE_EVENT && t && c);
@ -54,7 +54,7 @@ finish:
}
pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask m, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) {
pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, void (*cb)(pa_context *c, int success, void *userdata), void *userdata) {
pa_operation *o;
pa_tagstruct *t;
uint32_t tag;
@ -74,7 +74,7 @@ pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask m, void (
return pa_operation_ref(o);
}
void pa_context_set_subscribe_callback(pa_context *c, void (*cb)(pa_context *c, pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata) {
void pa_context_set_subscribe_callback(pa_context *c, void (*cb)(pa_context *c, pa_subscription_event_type_t t, uint32_t index, void *userdata), void *userdata) {
assert(c);
c->subscribe_callback = cb;
c->subscribe_userdata = userdata;

View file

@ -37,10 +37,10 @@
PA_C_DECL_BEGIN
/** Enable event notification */
pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask m, void (*cb)(pa_context *c, int success, void *userdata), void *userdata);
pa_operation* pa_context_subscribe(pa_context *c, pa_subscription_mask_t m, void (*cb)(pa_context *c, int success, void *userdata), void *userdata);
/** Set the context specific call back function that is called whenever the state of the daemon changes */
void pa_context_set_subscribe_callback(pa_context *c, void (*cb)(pa_context *c, pa_subscription_event_type t, uint32_t index, void *userdata), void *userdata);
void pa_context_set_subscribe_callback(pa_context *c, void (*cb)(pa_context *c, pa_subscription_event_type_t t, uint32_t index, void *userdata), void *userdata);
PA_C_DECL_END

View file

@ -64,8 +64,6 @@
#define SCACHE_PREFIX "esound."
#define PA_TYPEID_ESOUND PA_TYPEID_MAKE('E', 'S', 'D', 'P')
/* This is heavily based on esound's code */
struct connection {
@ -326,7 +324,7 @@ static int esd_proto_stream_play(struct connection *c, PA_GCC_UNUSED esd_proto_t
assert(!c->sink_input && !c->input_memblockq);
if (!(c->sink_input = pa_sink_input_new(sink, PA_TYPEID_ESOUND, name, &ss, 0, -1))) {
if (!(c->sink_input = pa_sink_input_new(sink, __FILE__, name, &ss, NULL, 0, -1))) {
pa_log(__FILE__": failed to create sink input.\n");
return -1;
}
@ -398,7 +396,7 @@ static int esd_proto_stream_record(struct connection *c, esd_proto_t request, co
assert(!c->output_memblockq && !c->source_output);
if (!(c->source_output = pa_source_output_new(source, PA_TYPEID_ESOUND, name, &ss, -1))) {
if (!(c->source_output = pa_source_output_new(source, __FILE__, name, &ss, NULL, -1))) {
pa_log(__FILE__": failed to create source output\n");
return -1;
}
@ -476,7 +474,7 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v
assert(k);
for (conn = pa_idxset_first(c->protocol->connections, &idx); conn; conn = pa_idxset_next(c->protocol->connections, &idx)) {
int format = ESD_BITS16 | ESD_STEREO, rate = 44100, volume = 0xFF;
int format = ESD_BITS16 | ESD_STEREO, rate = 44100, lvolume = 0xFF, rvolume = 0xFF;
if (conn->state != ESD_STREAMING_DATA)
continue;
@ -485,7 +483,8 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v
if (conn->sink_input) {
rate = conn->sink_input->sample_spec.rate;
volume = (conn->sink_input->volume*0xFF)/0x100;
lvolume = (conn->sink_input->volume.values[0]*0xFF)/0x100;
rvolume = (conn->sink_input->volume.values[1]*0xFF)/0x100;
format = format_native2esd(&conn->sink_input->sample_spec);
}
@ -503,11 +502,11 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v
response += sizeof(int);
/* left */
*((int*) response) = maybe_swap_endian_32(c->swap_byte_order, volume);
*((int*) response) = maybe_swap_endian_32(c->swap_byte_order, lvolume);
response += sizeof(int);
/*right*/
*((int*) response) = maybe_swap_endian_32(c->swap_byte_order, volume);
*((int*) response) = maybe_swap_endian_32(c->swap_byte_order, rvolume);
response += sizeof(int);
/*format*/
@ -545,11 +544,11 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v
response += sizeof(int);
/* left */
*((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (ce->volume*0xFF)/0x100);
*((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (ce->volume.values[0]*0xFF)/0x100);
response += sizeof(int);
/*right*/
*((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (ce->volume*0xFF)/0x100);
*((int*) response) = maybe_swap_endian_32(c->swap_byte_order, (ce->volume.values[0]*0xFF)/0x100);
response += sizeof(int);
/*format*/
@ -572,20 +571,25 @@ static int esd_proto_all_info(struct connection *c, esd_proto_t request, const v
static int esd_proto_stream_pan(struct connection *c, PA_GCC_UNUSED esd_proto_t request, const void *data, size_t length) {
int *ok;
uint32_t idx, volume;
uint32_t idx;
pa_volume_t lvolume, rvolume;
struct connection *conn;
assert(c && data && length == sizeof(int)*3);
idx = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *(const int*)data)-1;
volume = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *((const int*)data + 1));
volume = (volume*0x100)/0xFF;
lvolume = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *((const int*)data + 1));
lvolume = (lvolume*0x100)/0xFF;
rvolume = (uint32_t) maybe_swap_endian_32(c->swap_byte_order, *((const int*)data + 2));
rvolume = (rvolume*0x100)/0xFF;
ok = connection_write(c, sizeof(int));
assert(ok);
if ((conn = pa_idxset_get_by_index(c->protocol->connections, idx))) {
assert(conn->sink_input);
conn->sink_input->volume = volume;
conn->sink_input->volume.values[0] = lvolume;
conn->sink_input->volume.values[1] = rvolume;
conn->sink_input->volume.channels = 2;
*ok = 1;
} else
*ok = 0;
@ -627,7 +631,7 @@ static int esd_proto_sample_cache(struct connection *c, PA_GCC_UNUSED esd_proto_
c->state = ESD_CACHING_SAMPLE;
pa_scache_add_item(c->protocol->core, c->scache.name, NULL, NULL, &idx);
pa_scache_add_item(c->protocol->core, c->scache.name, NULL, NULL, NULL, &idx);
ok = connection_write(c, sizeof(int));
assert(ok);
@ -676,7 +680,7 @@ static int esd_proto_sample_free_or_play(struct connection *c, esd_proto_t reque
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)
if (pa_scache_play_item(c->protocol->core, name, sink, NULL) >= 0)
*ok = (int) idx+1;
} else {
assert(request == ESD_PROTO_SAMPLE_FREE);
@ -801,7 +805,7 @@ static int do_read(struct connection *c) {
int *ok;
c->scache.memchunk.index = 0;
pa_scache_add_item(c->protocol->core, c->scache.name, &c->scache.sample_spec, &c->scache.memchunk, &idx);
pa_scache_add_item(c->protocol->core, c->scache.name, &c->scache.sample_spec, NULL, &c->scache.memchunk, &idx);
pa_memblock_unref(c->scache.memchunk.memblock);
c->scache.memchunk.memblock = NULL;
@ -1067,7 +1071,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname));
assert(p->core);
c->client = pa_client_new(p->core, PA_TYPEID_ESOUND, cname);
c->client = pa_client_new(p->core, __FILE__, cname);
assert(c->client);
c->client->owner = p->module;
c->client->kill = client_kill_cb;

View file

@ -56,8 +56,6 @@
/* Don't accept more connection than this */
#define MAX_CONNECTIONS 10
#define PA_TYPEID_NATIVE PA_TYPEID_MAKE('N', 'A', 'T', 'V')
struct connection;
struct pa_protocol_native;
@ -88,6 +86,7 @@ struct upload_stream {
size_t length;
char *name;
pa_sample_spec sample_spec;
pa_channel_map channel_map;
};
struct output_stream {
@ -235,7 +234,12 @@ static const pa_pdispatch_callback command_table[PA_COMMAND_MAX] = {
/* structure management */
static struct upload_stream* upload_stream_new(struct connection *c, const pa_sample_spec *ss, const char *name, size_t length) {
static struct upload_stream* upload_stream_new(
struct connection *c,
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);
@ -243,6 +247,7 @@ static struct upload_stream* upload_stream_new(struct connection *c, const pa_sa
s->type = UPLOAD_STREAM;
s->connection = c;
s->sample_spec = *ss;
s->channel_map = *map;
s->name = pa_xstrdup(name);
s->memchunk.memblock = NULL;
@ -268,13 +273,21 @@ static void upload_stream_free(struct upload_stream *o) {
pa_xfree(o);
}
static struct record_stream* record_stream_new(struct connection *c, pa_source *source, const pa_sample_spec *ss, const char *name, size_t maxlength, size_t fragment_size) {
static struct record_stream* record_stream_new(
struct connection *c,
pa_source *source,
const pa_sample_spec *ss,
const pa_channel_map *map,
const char *name,
size_t maxlength,
size_t fragment_size) {
struct record_stream *s;
pa_source_output *source_output;
size_t base;
assert(c && source && ss && name && maxlength);
if (!(source_output = pa_source_output_new(source, PA_TYPEID_NATIVE, name, ss, -1)))
if (!(source_output = pa_source_output_new(source, __FILE__, name, ss, map, -1)))
return NULL;
s = pa_xmalloc(sizeof(struct record_stream));
@ -308,17 +321,23 @@ static void record_stream_free(struct record_stream* r) {
pa_xfree(r);
}
static struct playback_stream* playback_stream_new(struct connection *c, pa_sink *sink, const pa_sample_spec *ss, const char *name,
size_t maxlength,
size_t tlength,
size_t prebuf,
size_t minreq,
pa_volume_t volume) {
static struct playback_stream* playback_stream_new(
struct connection *c,
pa_sink *sink,
const pa_sample_spec *ss,
const pa_channel_map *map,
const char *name,
size_t maxlength,
size_t tlength,
size_t prebuf,
size_t minreq,
pa_cvolume *volume) {
struct playback_stream *s;
pa_sink_input *sink_input;
assert(c && sink && ss && name && maxlength);
if (!(sink_input = pa_sink_input_new(sink, PA_TYPEID_NATIVE, name, ss, 0, -1)))
if (!(sink_input = pa_sink_input_new(sink, __FILE__, name, ss, map, 0, -1)))
return NULL;
s = pa_xmalloc(sizeof(struct playback_stream));
@ -340,7 +359,7 @@ static struct playback_stream* playback_stream_new(struct connection *c, pa_sink
s->requested_bytes = 0;
s->drain_request = 0;
s->sink_input->volume = volume;
s->sink_input->volume = *volume;
pa_idxset_put(c->output_streams, s, &s->index);
return s;
@ -561,14 +580,17 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
uint32_t sink_index;
const char *name, *sink_name;
pa_sample_spec ss;
pa_channel_map map;
pa_tagstruct *reply;
pa_sink *sink;
pa_volume_t volume;
pa_cvolume volume;
int corked;
assert(c && t && c->protocol && c->protocol->core);
if (pa_tagstruct_gets(t, &name) < 0 || !name ||
pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
pa_tagstruct_get_channel_map(t, &map) < 0 ||
pa_tagstruct_getu32(t, &sink_index) < 0 ||
pa_tagstruct_gets(t, &sink_name) < 0 ||
pa_tagstruct_getu32(t, &maxlength) < 0 ||
@ -576,13 +598,12 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
pa_tagstruct_getu32(t, &tlength) < 0 ||
pa_tagstruct_getu32(t, &prebuf) < 0 ||
pa_tagstruct_getu32(t, &minreq) < 0 ||
pa_tagstruct_getu32(t, &volume) < 0 ||
pa_tagstruct_get_cvolume(t, &volume) < 0 ||
!pa_tagstruct_eof(t)) {
protocol_error(c);
return;
}
if (!c->authorized) {
pa_pstream_send_error(c->pstream, tag, PA_ERROR_ACCESS);
return;
@ -599,7 +620,7 @@ static void command_create_playback_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GC
return;
}
if (!(s = playback_stream_new(c, sink, &ss, name, maxlength, tlength, prebuf, minreq, volume))) {
if (!(s = playback_stream_new(c, sink, &ss, &map, name, maxlength, tlength, prebuf, minreq, &volume))) {
pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID);
return;
}
@ -671,6 +692,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
uint32_t source_index;
const char *name, *source_name;
pa_sample_spec ss;
pa_channel_map map;
pa_tagstruct *reply;
pa_source *source;
int corked;
@ -678,6 +700,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
if (pa_tagstruct_gets(t, &name) < 0 || !name ||
pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
pa_tagstruct_get_channel_map(t, &map) < 0 ||
pa_tagstruct_getu32(t, &source_index) < 0 ||
pa_tagstruct_gets(t, &source_name) < 0 ||
pa_tagstruct_getu32(t, &maxlength) < 0 ||
@ -703,7 +726,7 @@ static void command_create_record_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
return;
}
if (!(s = record_stream_new(c, source, &ss, name, maxlength, fragment_size))) {
if (!(s = record_stream_new(c, source, &ss, &map, name, maxlength, fragment_size))) {
pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID);
return;
}
@ -984,11 +1007,13 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
size_t length;
const char *name;
pa_sample_spec ss;
pa_channel_map map;
pa_tagstruct *reply;
assert(c && t && c->protocol && c->protocol->core);
if (pa_tagstruct_gets(t, &name) < 0 || !name ||
pa_tagstruct_get_sample_spec(t, &ss) < 0 ||
pa_tagstruct_get_channel_map(t, &map) < 0 ||
pa_tagstruct_getu32(t, &length) < 0 ||
!pa_tagstruct_eof(t)) {
protocol_error(c);
@ -1005,7 +1030,7 @@ static void command_create_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
return;
}
if (!(s = upload_stream_new(c, &ss, name, length))) {
if (!(s = upload_stream_new(c, &ss, &map, name, length))) {
pa_pstream_send_error(c->pstream, tag, PA_ERROR_INVALID);
return;
}
@ -1042,21 +1067,22 @@ static void command_finish_upload_stream(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_
return;
}
pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->memchunk, &idx);
pa_scache_add_item(c->protocol->core, s->name, &s->sample_spec, &s->channel_map, &s->memchunk, &idx);
pa_pstream_send_simple_ack(c->pstream, tag);
upload_stream_free(s);
}
static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
struct connection *c = userdata;
uint32_t sink_index, volume;
uint32_t sink_index;
pa_cvolume volume;
pa_sink *sink;
const char *name, *sink_name;
assert(c && t);
if (pa_tagstruct_getu32(t, &sink_index) < 0 ||
pa_tagstruct_gets(t, &sink_name) < 0 ||
pa_tagstruct_getu32(t, &volume) < 0 ||
pa_tagstruct_get_cvolume(t, &volume) < 0 ||
pa_tagstruct_gets(t, &name) < 0 || !name ||
!pa_tagstruct_eof(t)) {
protocol_error(c);
@ -1078,7 +1104,7 @@ static void command_play_sample(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED ui
return;
}
if (pa_scache_play_item(c->protocol->core, name, sink, volume) < 0) {
if (pa_scache_play_item(c->protocol->core, name, sink, &volume) < 0) {
pa_pstream_send_error(c->pstream, tag, PA_ERROR_NOENTITY);
return;
}
@ -1116,12 +1142,13 @@ static void sink_fill_tagstruct(pa_tagstruct *t, pa_sink *sink) {
pa_tagstruct_puts(t, sink->name);
pa_tagstruct_puts(t, sink->description);
pa_tagstruct_put_sample_spec(t, &sink->sample_spec);
pa_tagstruct_put_channel_map(t, &sink->channel_map);
pa_tagstruct_putu32(t, sink->owner ? sink->owner->index : (uint32_t) -1);
pa_tagstruct_putu32(t, sink->volume);
pa_tagstruct_put_cvolume(t, pa_sink_get_volume(sink, PA_MIXER_HARDWARE));
pa_tagstruct_putu32(t, sink->monitor_source->index);
pa_tagstruct_puts(t, sink->monitor_source->name);
pa_tagstruct_put_usec(t, pa_sink_get_latency(sink));
pa_tagstruct_putu32(t, sink->typeid);
pa_tagstruct_puts(t, sink->driver);
}
static void source_fill_tagstruct(pa_tagstruct *t, pa_source *source) {
@ -1130,11 +1157,12 @@ static void source_fill_tagstruct(pa_tagstruct *t, pa_source *source) {
pa_tagstruct_puts(t, source->name);
pa_tagstruct_puts(t, source->description);
pa_tagstruct_put_sample_spec(t, &source->sample_spec);
pa_tagstruct_put_channel_map(t, &source->channel_map);
pa_tagstruct_putu32(t, source->owner ? source->owner->index : (uint32_t) -1);
pa_tagstruct_putu32(t, source->monitor_of ? source->monitor_of->index : (uint32_t) -1);
pa_tagstruct_puts(t, source->monitor_of ? source->monitor_of->name : NULL);
pa_tagstruct_put_usec(t, pa_source_get_latency(source));
pa_tagstruct_putu32(t, source->typeid);
pa_tagstruct_puts(t, source->driver);
}
static void client_fill_tagstruct(pa_tagstruct *t, pa_client *client) {
@ -1142,7 +1170,7 @@ static void client_fill_tagstruct(pa_tagstruct *t, pa_client *client) {
pa_tagstruct_putu32(t, client->index);
pa_tagstruct_puts(t, client->name);
pa_tagstruct_putu32(t, client->owner ? client->owner->index : (uint32_t) -1);
pa_tagstruct_putu32(t, client->typeid);
pa_tagstruct_puts(t, client->driver);
}
static void module_fill_tagstruct(pa_tagstruct *t, pa_module *module) {
@ -1162,11 +1190,12 @@ static void sink_input_fill_tagstruct(pa_tagstruct *t, pa_sink_input *s) {
pa_tagstruct_putu32(t, s->client ? s->client->index : (uint32_t) -1);
pa_tagstruct_putu32(t, s->sink->index);
pa_tagstruct_put_sample_spec(t, &s->sample_spec);
pa_tagstruct_putu32(t, s->volume);
pa_tagstruct_put_channel_map(t, &s->channel_map);
pa_tagstruct_put_cvolume(t, &s->volume);
pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s));
pa_tagstruct_put_usec(t, pa_sink_get_latency(s->sink));
pa_tagstruct_puts(t, pa_resample_method_to_string(pa_sink_input_get_resample_method(s)));
pa_tagstruct_putu32(t, s->typeid);
pa_tagstruct_puts(t, s->driver);
}
static void source_output_fill_tagstruct(pa_tagstruct *t, pa_source_output *s) {
@ -1177,19 +1206,21 @@ static void source_output_fill_tagstruct(pa_tagstruct *t, pa_source_output *s) {
pa_tagstruct_putu32(t, s->client ? s->client->index : (uint32_t) -1);
pa_tagstruct_putu32(t, s->source->index);
pa_tagstruct_put_sample_spec(t, &s->sample_spec);
pa_tagstruct_put_channel_map(t, &s->channel_map);
pa_tagstruct_put_usec(t, pa_source_output_get_latency(s));
pa_tagstruct_put_usec(t, pa_source_get_latency(s->source));
pa_tagstruct_puts(t, pa_resample_method_to_string(pa_source_output_get_resample_method(s)));
pa_tagstruct_putu32(t, s->typeid);
pa_tagstruct_puts(t, s->driver);
}
static void scache_fill_tagstruct(pa_tagstruct *t, pa_scache_entry *e) {
assert(t && e);
pa_tagstruct_putu32(t, e->index);
pa_tagstruct_puts(t, e->name);
pa_tagstruct_putu32(t, e->volume);
pa_tagstruct_put_cvolume(t, &e->volume);
pa_tagstruct_put_usec(t, pa_bytes_to_usec(e->memchunk.length, &e->sample_spec));
pa_tagstruct_put_sample_spec(t, &e->sample_spec);
pa_tagstruct_put_channel_map(t, &e->channel_map);
pa_tagstruct_putu32(t, e->memchunk.length);
pa_tagstruct_put_boolean(t, e->lazy);
pa_tagstruct_puts(t, e->filename);
@ -1379,7 +1410,7 @@ static void command_get_server_info(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSE
pa_pstream_send_tagstruct(c->pstream, reply);
}
static void subscription_cb(pa_core *core, pa_subscription_event_type e, uint32_t idx, void *userdata) {
static void subscription_cb(pa_core *core, pa_subscription_event_type_t e, uint32_t idx, void *userdata) {
pa_tagstruct *t;
struct connection *c = userdata;
assert(c && core);
@ -1395,7 +1426,7 @@ static void subscription_cb(pa_core *core, pa_subscription_event_type e, uint32_
static void command_subscribe(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_subscription_mask m;
pa_subscription_mask_t m;
assert(c && t);
if (pa_tagstruct_getu32(t, &m) < 0 ||
@ -1423,7 +1454,8 @@ static void command_subscribe(PA_GCC_UNUSED pa_pdispatch *pd, PA_GCC_UNUSED uint
static void command_set_volume(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
struct connection *c = userdata;
uint32_t idx, volume;
uint32_t idx;
pa_cvolume volume;
pa_sink *sink = NULL;
pa_sink_input *si = NULL;
const char *name = NULL;
@ -1431,7 +1463,7 @@ static void command_set_volume(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command,
if (pa_tagstruct_getu32(t, &idx) < 0 ||
(command == PA_COMMAND_SET_SINK_VOLUME && pa_tagstruct_gets(t, &name) < 0) ||
pa_tagstruct_getu32(t, &volume) ||
pa_tagstruct_get_cvolume(t, &volume) ||
!pa_tagstruct_eof(t)) {
protocol_error(c);
return;
@ -1458,9 +1490,9 @@ static void command_set_volume(PA_GCC_UNUSED pa_pdispatch *pd, uint32_t command,
}
if (sink)
pa_sink_set_volume(sink, volume);
pa_sink_set_volume(sink, PA_MIXER_HARDWARE, &volume);
else if (si)
pa_sink_input_set_volume(si, volume);
pa_sink_input_set_volume(si, &volume);
pa_pstream_send_simple_ack(c->pstream, tag);
}
@ -2032,7 +2064,7 @@ static void on_connection(PA_GCC_UNUSED pa_socket_server*s, pa_iochannel *io, vo
c->protocol = p;
assert(p->core);
c->client = pa_client_new(p->core, PA_TYPEID_NATIVE, "Client");
c->client = pa_client_new(p->core, __FILE__, "Client");
assert(c->client);
c->client->kill = client_kill_cb;
c->client->userdata = c;

View file

@ -42,8 +42,6 @@
/* Don't allow more than this many concurrent connections */
#define MAX_CONNECTIONS 10
#define PA_TYPEID_SIMPLE PA_TYPEID_MAKE('S', 'M', 'P', 'L')
struct connection {
pa_protocol_simple *protocol;
pa_iochannel *io;
@ -310,7 +308,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
c->playback.fragment_size = 0;
pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname));
c->client = pa_client_new(p->core, PA_TYPEID_SIMPLE, cname);
c->client = pa_client_new(p->core, __FILE__, cname);
assert(c->client);
c->client->owner = p->module;
c->client->kill = client_kill_cb;
@ -325,7 +323,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
goto fail;
}
if (!(c->sink_input = pa_sink_input_new(sink, PA_TYPEID_SIMPLE, c->client->name, &p->sample_spec, 0, -1))) {
if (!(c->sink_input = pa_sink_input_new(sink, __FILE__, c->client->name, &p->sample_spec, NULL, 0, -1))) {
pa_log(__FILE__": Failed to create sink input.\n");
goto fail;
}
@ -355,7 +353,7 @@ static void on_connection(pa_socket_server*s, pa_iochannel *io, void *userdata)
goto fail;
}
c->source_output = pa_source_output_new(source, PA_TYPEID_SIMPLE, c->client->name, &p->sample_spec, -1);
c->source_output = pa_source_output_new(source, __FILE__, c->client->name, &p->sample_spec, NULL, -1);
if (!c->source_output) {
pa_log(__FILE__": Failed to create source output.\n");
goto fail;

View file

@ -27,6 +27,8 @@
#include <string.h>
#include <samplerate.h>
#include <liboil/liboilfuncs.h>
#include <liboil/liboil.h>
#include "resampler.h"
#include "sconv.h"
@ -34,24 +36,28 @@
#include "log.h"
struct pa_resampler {
pa_resample_method_t resample_method;
pa_sample_spec i_ss, o_ss;
pa_channel_map i_cm, o_cm;
size_t i_fz, o_fz;
pa_memblock_stat *memblock_stat;
void *impl_data;
int channels;
pa_resample_method resample_method;
void (*impl_free)(pa_resampler *r);
void (*impl_set_input_rate)(pa_resampler *r, uint32_t rate);
void (*impl_update_input_rate)(pa_resampler *r, uint32_t rate);
void (*impl_run)(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out);
void *impl_data;
};
struct impl_libsamplerate {
float* i_buf, *o_buf;
unsigned i_alloc, o_alloc;
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;
int map_table[PA_CHANNELS_MAX][PA_CHANNELS_MAX];
int map_required;
};
struct impl_trivial {
@ -62,35 +68,54 @@ struct impl_trivial {
static int libsamplerate_init(pa_resampler*r);
static int trivial_init(pa_resampler*r);
pa_resampler* pa_resampler_new(const pa_sample_spec *a, const pa_sample_spec *b, pa_memblock_stat *s, pa_resample_method resample_method) {
pa_resampler* pa_resampler_new(
const pa_sample_spec *a,
const pa_channel_map *am,
const pa_sample_spec *b,
const pa_channel_map *bm,
pa_memblock_stat *s,
pa_resample_method_t resample_method) {
pa_resampler *r = NULL;
assert(a && b && pa_sample_spec_valid(a) && pa_sample_spec_valid(b) && resample_method != PA_RESAMPLER_INVALID);
if (a->channels != b->channels && a->channels != 1 && b->channels != 1)
goto fail;
assert(a);
assert(b);
assert(pa_sample_spec_valid(a));
assert(pa_sample_spec_valid(b));
assert(resample_method != PA_RESAMPLER_INVALID);
r = pa_xmalloc(sizeof(pa_resampler));
r = pa_xnew(pa_resampler, 1);
r->impl_data = NULL;
r->memblock_stat = s;
r->resample_method = resample_method;
r->impl_free = NULL;
r->impl_set_input_rate = NULL;
r->impl_update_input_rate = NULL;
r->impl_run = NULL;
/* Fill sample specs */
r->i_ss = *a;
r->o_ss = *b;
if (am)
r->i_cm = *am;
else
pa_channel_map_init_auto(&r->i_cm, r->i_ss.channels);
if (bm)
r->o_cm = *bm;
else
pa_channel_map_init_auto(&r->o_cm, r->o_ss.channels);
r->i_fz = pa_frame_size(a);
r->o_fz = pa_frame_size(b);
r->channels = a->channels;
if (b->channels < r->channels)
r->channels = b->channels;
/* Choose implementation */
if (a->channels != b->channels || a->format != b->format || resample_method != PA_RESAMPLER_TRIVIAL) {
if (a->channels != b->channels ||
a->format != b->format ||
!pa_channel_map_equal(&r->i_cm, &r->o_cm) ||
resample_method != PA_RESAMPLER_TRIVIAL) {
/* Use the libsamplerate based resampler for the complicated cases */
if (resample_method == PA_RESAMPLER_TRIVIAL)
r->resample_method = PA_RESAMPLER_SRC_ZERO_ORDER_HOLD;
@ -123,11 +148,16 @@ void pa_resampler_free(pa_resampler *r) {
}
void pa_resampler_set_input_rate(pa_resampler *r, uint32_t rate) {
assert(r && rate);
assert(r);
assert(rate > 0);
if (r->i_ss.rate == rate)
return;
r->i_ss.rate = rate;
if (r->impl_set_input_rate)
r->impl_set_input_rate(r, rate);
if (r->impl_update_input_rate)
r->impl_update_input_rate(r, rate);
}
void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) {
@ -141,168 +171,342 @@ size_t pa_resampler_request(pa_resampler *r, size_t out_length) {
return (((out_length / r->o_fz)*r->i_ss.rate)/r->o_ss.rate) * r->i_fz;
}
pa_resample_method pa_resampler_get_method(pa_resampler *r) {
pa_resample_method_t pa_resampler_get_method(pa_resampler *r) {
assert(r);
return r->resample_method;
}
/* Parse a libsamplrate compatible resampling implementation */
pa_resample_method pa_parse_resample_method(const char *string) {
static const char * const resample_methods[] = {
"src-sinc-best-quality",
"src-sinc-medium-quality",
"src-sinc-fastest",
"src-zero-order-hold",
"src-linear",
"trivial"
};
const char *pa_resample_method_to_string(pa_resample_method_t m) {
if (m < 0 || m >= PA_RESAMPLER_MAX)
return NULL;
return resample_methods[m];
}
pa_resample_method_t pa_parse_resample_method(const char *string) {
pa_resample_method_t m;
assert(string);
if (!strcmp(string, "src-sinc-best-quality"))
return PA_RESAMPLER_SRC_SINC_BEST_QUALITY;
else if (!strcmp(string, "src-sinc-medium-quality"))
return PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY;
else if (!strcmp(string, "src-sinc-fastest"))
return PA_RESAMPLER_SRC_SINC_FASTEST;
else if (!strcmp(string, "src-zero-order-hold"))
return PA_RESAMPLER_SRC_ZERO_ORDER_HOLD;
else if (!strcmp(string, "src-linear"))
return PA_RESAMPLER_SRC_LINEAR;
else if (!strcmp(string, "trivial"))
return PA_RESAMPLER_TRIVIAL;
else
return PA_RESAMPLER_INVALID;
for (m = 0; m < PA_RESAMPLER_MAX; m++)
if (!strcmp(string, resample_methods[m]))
return m;
return PA_RESAMPLER_INVALID;
}
/*** libsamplerate based implementation ***/
static void libsamplerate_free(pa_resampler *r) {
struct impl_libsamplerate *i;
assert(r && r->impl_data);
i = r->impl_data;
if (i->src_state)
src_delete(i->src_state);
struct impl_libsamplerate *u;
pa_xfree(i->i_buf);
pa_xfree(i->o_buf);
pa_xfree(i);
assert(r);
assert(r->impl_data);
u = r->impl_data;
if (u->src_state)
src_delete(u->src_state);
pa_xfree(u->buf1);
pa_xfree(u->buf2);
pa_xfree(u->buf3);
pa_xfree(u->buf4);
pa_xfree(u);
}
static void calc_map_table(pa_resampler *r) {
struct impl_libsamplerate *u;
unsigned oc;
assert(r);
assert(r->impl_data);
u = r->impl_data;
if (!(u->map_required = (!pa_channel_map_equal(&r->i_cm, &r->o_cm) || r->i_ss.channels != r->o_ss.channels)))
return;
for (oc = 0; oc < r->o_ss.channels; oc++) {
unsigned ic, i = 0;
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;
}
/* Add an end marker */
if (i < PA_CHANNELS_MAX)
u->map_table[oc][i] = -1;
}
}
static float * convert_to_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 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 = pa_xrealloc(u->buf1, sizeof(float) * (u->buf1_samples = n_samples));
u->to_float32ne_func(n_samples, input, u->buf1);
return u->buf1;
}
static float *remap_channels(pa_resampler *r, float *input, unsigned n_frames) {
struct impl_libsamplerate *u;
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;
n_samples = n_frames * r->o_ss.channels;
if (u->buf2_samples < n_samples)
u->buf2 = pa_xrealloc(u->buf2, sizeof(float) * (u->buf2_samples = n_samples));
memset(u->buf2, 0, n_samples * sizeof(float));
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;
for (i = 0; i < PA_CHANNELS_MAX && u->map_table[oc][i] >= 0; i++)
oil_vectoradd_f32(
u->buf2 + oc, o_skip,
u->buf2 + oc, o_skip,
input + u->map_table[oc][i], i_skip,
n_frames,
&one, &one);
}
return u->buf2;
}
static float *resample(pa_resampler *r, float *input, unsigned *n_frames) {
struct impl_libsamplerate *u;
SRC_DATA data;
unsigned out_n_frames, out_n_samples;
int ret;
assert(r);
assert(input);
assert(n_frames);
assert(r->impl_data);
u = r->impl_data;
/* Resample the data and place the result in buf3 */
if (!u->src_state)
return input;
out_n_frames = (*n_frames*r->o_ss.rate/r->i_ss.rate)+1024;
out_n_samples = out_n_frames * r->o_ss.channels;
if (u->buf3_samples < out_n_samples)
u->buf3 = pa_xrealloc(u->buf3, sizeof(float) * (u->buf3_samples = out_n_samples));
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);
*n_frames = data.output_frames_gen;
return u->buf3;
}
static float *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 = pa_xrealloc(u->buf4, sizeof(float) * (u->buf4_samples = n_samples));
u->from_float32ne_func(n_samples, input, u->buf4);
return u->buf4;
}
static void libsamplerate_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) {
unsigned i_nchannels, o_nchannels, ins, ons, eff_ins, eff_ons;
float *cbuf;
struct impl_libsamplerate *i;
assert(r && in && out && in->length && in->memblock && (in->length % r->i_fz) == 0 && r->impl_data);
i = r->impl_data;
struct impl_libsamplerate *u;
float *buf, *input;
unsigned n_frames;
/* How many input samples? */
ins = in->length/r->i_fz;
/* pa_log("%u / %u = %u\n", in->length, r->i_fz, ins); */
/* How much space for output samples? */
if (i->src_state)
ons = (ins*r->o_ss.rate/r->i_ss.rate)+1024;
else
ons = ins;
assert(r);
assert(in);
assert(out);
assert(in->length);
assert(in->memblock);
assert(in->length % r->i_fz == 0);
assert(r->impl_data);
/* How many channels? */
if (r->i_ss.channels == r->o_ss.channels) {
i_nchannels = o_nchannels = 1;
eff_ins = ins*r->i_ss.channels; /* effective samples */
eff_ons = ons*r->o_ss.channels;
u = r->impl_data;
buf = input = (float*) ((uint8_t*) in->memblock->data + in->index);
n_frames = in->length / r->i_fz;
assert(n_frames > 0);
buf = convert_to_float(r, buf, n_frames);
buf = remap_channels(r, buf, n_frames);
buf = resample(r, buf, &n_frames);
if (n_frames) {
buf = convert_from_float(r, buf, n_frames);
if (buf == input) {
/* Mm, no adjustment has been necessary, so let's return the original block */
out->memblock = pa_memblock_ref(in->memblock);
out->index = in->index;
out->length = in->length;
} else {
float **p = NULL;
out->length = n_frames * r->o_fz;
out->index = 0;
if (buf == u->buf1) {
p = &u->buf1;
u->buf1_samples = 0;
} else if (buf == u->buf2) {
p = &u->buf2;
u->buf2_samples = 0;
} else if (buf == u->buf3) {
p = &u->buf3;
u->buf3_samples = 0;
} else if (buf == u->buf4) {
p = &u->buf4;
u->buf4_samples = 0;
}
assert(p);
/* Take the existing buffer and make it a memblock */
out->memblock = pa_memblock_new_dynamic(*p, out->length, r->memblock_stat);
*p = NULL;
}
} else {
i_nchannels = r->i_ss.channels;
o_nchannels = r->o_ss.channels;
eff_ins = ins;
eff_ons = ons;
}
/* pa_log("eff_ins = %u \n", eff_ins); */
out->memblock = pa_memblock_new(out->length = (ons*r->o_fz), r->memblock_stat);
out->index = 0;
assert(out->memblock);
if (i->i_alloc < eff_ins)
i->i_buf = pa_xrealloc(i->i_buf, sizeof(float) * (i->i_alloc = eff_ins));
assert(i->i_buf);
/* pa_log("eff_ins = %u \n", eff_ins); */
i->to_float32ne_func(eff_ins, (uint8_t*) in->memblock->data+in->index, i_nchannels, i->i_buf);
if (i->src_state) {
int ret;
SRC_DATA data;
if (i->o_alloc < eff_ons)
i->o_buf = pa_xrealloc(i->o_buf, sizeof(float) * (i->o_alloc = eff_ons));
assert(i->o_buf);
data.data_in = i->i_buf;
data.input_frames = ins;
data.data_out = i->o_buf;
data.output_frames = ons;
data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate;
data.end_of_input = 0;
ret = src_process(i->src_state, &data);
assert(ret == 0);
assert((unsigned) data.input_frames_used == ins);
cbuf = i->o_buf;
ons = data.output_frames_gen;
if (r->i_ss.channels == r->o_ss.channels)
eff_ons = ons*r->o_ss.channels;
else
eff_ons = ons;
} else
cbuf = i->i_buf;
if (eff_ons)
i->from_float32ne_func(eff_ons, cbuf, (uint8_t*)out->memblock->data+out->index, o_nchannels);
out->length = ons*r->o_fz;
if (!out->length) {
pa_memblock_unref(out->memblock);
out->memblock = NULL;
out->index = out->length = 0;
}
}
static void libsamplerate_set_input_rate(pa_resampler *r, uint32_t rate) {
int ret;
struct impl_libsamplerate *i;
assert(r && rate > 0 && r->impl_data);
i = r->impl_data;
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);
u = r->impl_data;
ret = src_set_ratio(i->src_state, (double) r->o_ss.rate / r->i_ss.rate);
assert(ret == 0);
if (!u->src_state) {
int err;
u->src_state = src_new(r->resample_method, r->o_ss.channels, &err);
assert(u->src_state);
} else {
int ret = src_set_ratio(u->src_state, (double) r->o_ss.rate / rate);
assert(ret == 0);
}
}
static int libsamplerate_init(pa_resampler *r) {
struct impl_libsamplerate *i = NULL;
struct impl_libsamplerate *u = NULL;
int err;
r->impl_data = i = pa_xmalloc(sizeof(struct impl_libsamplerate));
i->to_float32ne_func = pa_get_convert_to_float32ne_function(r->i_ss.format);
i->from_float32ne_func = pa_get_convert_from_float32ne_function(r->o_ss.format);
r->impl_data = u = pa_xnew(struct impl_libsamplerate, 1);
if (!i->to_float32ne_func || !i->from_float32ne_func)
goto fail;
if (!(i->src_state = src_new(r->resample_method, r->channels, &err)) || !i->src_state)
u->buf1 = u->buf2 = u->buf3 = u->buf4 = NULL;
u->buf1_samples = u->buf2_samples = u->buf3_samples = u->buf4_samples = 0;
if (r->i_ss.format == PA_SAMPLE_FLOAT32NE)
u->to_float32ne_func = NULL;
else if (!(u->to_float32ne_func = pa_get_convert_to_float32ne_function(r->i_ss.format)))
goto fail;
i->i_buf = i->o_buf = NULL;
i->i_alloc = i->o_alloc = 0;
if (r->o_ss.format == PA_SAMPLE_FLOAT32NE)
u->from_float32ne_func = NULL;
else if (!(u->from_float32ne_func = pa_get_convert_from_float32ne_function(r->o_ss.format)))
goto fail;
if (r->o_ss.rate == r->i_ss.rate)
u->src_state = NULL;
else if (!(u->src_state = src_new(r->resample_method, r->o_ss.channels, &err)))
goto fail;
r->impl_free = libsamplerate_free;
r->impl_set_input_rate = libsamplerate_set_input_rate;
r->impl_update_input_rate = libsamplerate_update_input_rate;
r->impl_run = libsamplerate_run;
calc_map_table(r);
return 0;
fail:
pa_xfree(i);
pa_xfree(u);
return -1;
}
@ -310,15 +514,20 @@ fail:
static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) {
size_t fz;
unsigned nframes;
struct impl_trivial *i;
assert(r && in && out && r->impl_data);
i = r->impl_data;
unsigned n_frames;
struct impl_trivial *u;
assert(r);
assert(in);
assert(out);
assert(r->impl_data);
u = r->impl_data;
fz = r->i_fz;
assert(fz == r->o_fz);
nframes = in->length/fz;
n_frames = in->length/fz;
if (r->i_ss.rate == r->o_ss.rate) {
@ -326,25 +535,25 @@ static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out
*out = *in;
pa_memblock_ref(out->memblock);
i->o_counter += nframes;
u->o_counter += n_frames;
} else {
/* Do real resampling */
size_t l;
unsigned o_index;
/* The length of the new memory block rounded up */
l = ((((nframes+1) * r->o_ss.rate) / r->i_ss.rate) + 1) * fz;
l = ((((n_frames+1) * r->o_ss.rate) / r->i_ss.rate) + 1) * fz;
out->index = 0;
out->memblock = pa_memblock_new(l, r->memblock_stat);
for (o_index = 0;; o_index++, i->o_counter++) {
for (o_index = 0;; o_index++, u->o_counter++) {
unsigned j;
j = (i->o_counter * r->i_ss.rate / r->o_ss.rate);
j = j > i->i_counter ? j - i->i_counter : 0;
j = (u->o_counter * r->i_ss.rate / r->o_ss.rate);
j = j > u->i_counter ? j - u->i_counter : 0;
if (j >= nframes)
if (j >= n_frames)
break;
assert(o_index*fz < out->memblock->length);
@ -357,56 +566,49 @@ static void trivial_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out
out->length = o_index*fz;
}
i->i_counter += nframes;
u->i_counter += n_frames;
/* Normalize counters */
while (i->i_counter >= r->i_ss.rate) {
i->i_counter -= r->i_ss.rate;
assert(i->o_counter >= r->o_ss.rate);
i->o_counter -= r->o_ss.rate;
while (u->i_counter >= r->i_ss.rate) {
u->i_counter -= r->i_ss.rate;
assert(u->o_counter >= r->o_ss.rate);
u->o_counter -= r->o_ss.rate;
}
}
static void trivial_free(pa_resampler *r) {
assert(r);
pa_xfree(r->impl_data);
}
static void trivial_set_input_rate(pa_resampler *r, uint32_t rate) {
struct impl_trivial *i;
assert(r && rate > 0 && r->impl_data);
i = r->impl_data;
static void trivial_update_input_rate(pa_resampler *r, uint32_t rate) {
struct impl_trivial *u;
i->i_counter = 0;
i->o_counter = 0;
assert(r);
assert(rate > 0);
assert(r->impl_data);
u = r->impl_data;
u->i_counter = 0;
u->o_counter = 0;
}
static int trivial_init(pa_resampler*r) {
struct impl_trivial *i;
assert(r && r->i_ss.format == r->o_ss.format && r->i_ss.channels == r->o_ss.channels);
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_data = i = pa_xmalloc(sizeof(struct impl_trivial));
i->o_counter = i->i_counter = 0;
r->impl_data = u = pa_xnew(struct impl_trivial, 1);
u->o_counter = u->i_counter = 0;
r->impl_run = trivial_run;
r->impl_free = trivial_free;
r->impl_set_input_rate = trivial_set_input_rate;
r->impl_update_input_rate = trivial_update_input_rate;
return 0;
}
const char *pa_resample_method_to_string(pa_resample_method m) {
static const char * const resample_methods[] = {
"src-sinc-best-quality",
"src-sinc-medium-quality",
"src-sinc-fastest",
"src-zero-order-hold",
"src-linear",
"trivial"
};
if (m < 0 || m >= PA_RESAMPLER_MAX)
return NULL;
return resample_methods[m];
}

View file

@ -27,6 +27,7 @@
#include "sample.h"
#include "memblock.h"
#include "memchunk.h"
#include "channelmap.h"
typedef struct pa_resampler pa_resampler;
@ -39,9 +40,16 @@ typedef enum pa_resample_method {
PA_RESAMPLER_SRC_LINEAR = SRC_LINEAR,
PA_RESAMPLER_TRIVIAL,
PA_RESAMPLER_MAX
} pa_resample_method;
} pa_resample_method_t;
pa_resampler* pa_resampler_new(
const pa_sample_spec *a,
const pa_channel_map *am,
const pa_sample_spec *b,
const pa_channel_map *bm,
pa_memblock_stat *s,
pa_resample_method_t resample_method);
pa_resampler* pa_resampler_new(const pa_sample_spec *a, const pa_sample_spec *b, pa_memblock_stat *s, int resample_method);
void pa_resampler_free(pa_resampler *r);
/* Returns the size of an input memory block which is required to return the specified amount of output data */
@ -54,12 +62,12 @@ void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out);
void pa_resampler_set_input_rate(pa_resampler *r, uint32_t rate);
/* Return the resampling method of the resampler object */
pa_resample_method pa_resampler_get_method(pa_resampler *r);
pa_resample_method_t pa_resampler_get_method(pa_resampler *r);
/* Try to parse the resampler method */
pa_resample_method pa_parse_resample_method(const char *string);
pa_resample_method_t pa_parse_resample_method(const char *string);
/* return a human readable string for the specified resampling method. Inverse of pa_parse_resample_method() */
const char *pa_resample_method_to_string(pa_resample_method m);
const char *pa_resample_method_to_string(pa_resample_method_t m);
#endif

View file

@ -28,6 +28,8 @@
#include <assert.h>
#include <stdlib.h>
#include <liboil/liboilfuncs.h>
#include "sample-util.h"
pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) {
@ -38,6 +40,7 @@ pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) {
void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) {
assert(c && c->memblock && c->memblock->data && spec && c->length);
pa_silence_memory((uint8_t*) c->memblock->data+c->index, c->length, spec);
}
@ -65,204 +68,255 @@ void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) {
memset(p, c, length);
}
size_t pa_mix(pa_mix_info channels[], unsigned nchannels, void *data, size_t length, const pa_sample_spec *spec, pa_volume_t volume) {
assert(channels && data && length && spec);
size_t pa_mix(
const pa_mix_info streams[],
unsigned nstreams,
void *data,
size_t length,
const pa_sample_spec *spec,
const pa_cvolume *volume) {
if (spec->format == PA_SAMPLE_S16NE) {
size_t d;
for (d = 0;; d += sizeof(int16_t)) {
unsigned c;
int32_t sum = 0;
assert(streams && data && length && spec);
switch (spec->format) {
case PA_SAMPLE_S16NE:{
size_t d;
unsigned channel = 0;
if (d >= length)
return d;
for (c = 0; c < nchannels; c++) {
int32_t v;
pa_volume_t cvolume = channels[c].volume;
for (d = 0;; d += sizeof(int16_t)) {
int32_t sum = 0;
if (d >= channels[c].chunk.length)
if (d >= length)
return d;
if (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 *= cvolume;
v /= PA_VOLUME_NORM;
}
}
sum += v;
}
if (volume->values[channel] != PA_VOLUME_NORM) {
sum *= volume->values[channel];
sum /= PA_VOLUME_NORM;
}
if (sum < -0x8000) sum = -0x8000;
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_U8: {
size_t d;
unsigned channel = 0;
for (d = 0;; d ++) {
int32_t sum = 0;
if (d >= length)
return d;
if (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 *= cvolume;
v /= PA_VOLUME_NORM;
}
}
sum += v;
}
if (volume->values[channel] != PA_VOLUME_NORM) {
sum *= volume->values[channel];
sum /= PA_VOLUME_NORM;
}
if (sum < -0x80) sum = -0x80;
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 (cvolume == PA_VOLUME_MUTED)
v = 0;
else {
v = *((int16_t*) ((uint8_t*) channels[c].chunk.memblock->data + channels[c].chunk.index + d));
if (volume->values[channel] != PA_VOLUME_MUTED) {
unsigned i;
if (cvolume != PA_VOLUME_NORM) {
v *= cvolume;
v /= PA_VOLUME_NORM;
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 *= cvolume;
v /= PA_VOLUME_NORM;
}
}
sum += v;
}
if (volume->values[channel] != PA_VOLUME_NORM) {
sum *= volume->values[channel];
sum /= PA_VOLUME_NORM;
}
}
sum += v;
*((float*) data) = sum;
data = (uint8_t*) data + sizeof(float);
if (++channel >= spec->channels)
channel = 0;
}
if (volume == PA_VOLUME_MUTED)
sum = 0;
else if (volume != PA_VOLUME_NORM) {
sum *= volume;
sum /= PA_VOLUME_NORM;
}
if (sum < -0x8000) sum = -0x8000;
if (sum > 0x7FFF) sum = 0x7FFF;
*((int16_t*) data) = sum;
data = (uint8_t*) data + sizeof(int16_t);
}
} else if (spec->format == PA_SAMPLE_U8) {
size_t d;
for (d = 0;; d ++) {
int32_t sum = 0;
unsigned c;
if (d >= length)
return d;
for (c = 0; c < nchannels; c++) {
int32_t v;
pa_volume_t cvolume = channels[c].volume;
if (d >= channels[c].chunk.length)
return d;
if (cvolume == PA_VOLUME_MUTED)
v = 0;
else {
v = (int32_t) *((uint8_t*) channels[c].chunk.memblock->data + channels[c].chunk.index + d) - 0x80;
if (cvolume != PA_VOLUME_NORM) {
v *= cvolume;
v /= PA_VOLUME_NORM;
}
}
sum += v;
}
if (volume == PA_VOLUME_MUTED)
sum = 0;
else if (volume != PA_VOLUME_NORM) {
sum *= volume;
sum /= PA_VOLUME_NORM;
}
if (sum < -0x80) sum = -0x80;
if (sum > 0x7F) sum = 0x7F;
*((uint8_t*) data) = (uint8_t) (sum + 0x80);
data = (uint8_t*) data + 1;
}
} else if (spec->format == PA_SAMPLE_FLOAT32NE) {
size_t d;
for (d = 0;; d += sizeof(float)) {
float sum = 0;
unsigned c;
if (d >= length)
return d;
for (c = 0; c < nchannels; c++) {
float v;
pa_volume_t cvolume = channels[c].volume;
if (d >= channels[c].chunk.length)
return d;
if (cvolume == PA_VOLUME_MUTED)
v = 0;
else {
v = *((float*) ((uint8_t*) channels[c].chunk.memblock->data + channels[c].chunk.index + d));
if (cvolume != PA_VOLUME_NORM)
v = v*cvolume/PA_VOLUME_NORM;
}
sum += v;
}
if (volume == PA_VOLUME_MUTED)
sum = 0;
else if (volume != PA_VOLUME_NORM)
sum = sum*volume/PA_VOLUME_NORM;
if (sum < -1) sum = -1;
if (sum > 1) sum = 1;
*((float*) data) = sum;
data = (uint8_t*) data + sizeof(float);
}
} else {
abort();
default:
abort();
}
}
void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, pa_volume_t volume) {
void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvolume *volume) {
assert(c && spec && (c->length % pa_frame_size(spec) == 0));
assert(volume);
if (volume == PA_VOLUME_NORM)
if (pa_cvolume_channels_equal_to(volume, PA_VOLUME_NORM))
return;
if (volume == PA_VOLUME_MUTED) {
if (pa_cvolume_channels_equal_to(volume, PA_VOLUME_MUTED)) {
pa_silence_memchunk(c, spec);
return;
}
if (spec->format == PA_SAMPLE_S16NE) {
int16_t *d;
size_t n;
switch (spec->format) {
case PA_SAMPLE_S16NE: {
int16_t *d;
size_t n;
unsigned channel = 0;
for (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 *= volume->values[channel];
t /= PA_VOLUME_NORM;
if (t < -0x8000) t = -0x8000;
if (t > 0x7FFF) t = 0x7FFF;
*d = (int16_t) t;
if (++channel >= spec->channels)
channel = 0;
}
}
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 *= volume->values[channel];
t /= PA_VOLUME_NORM;
if (t < -0x80) t = -0x80;
if (t > 0x7F) t = 0x7F;
*d = (uint8_t) (t + 0x80);
if (++channel >= spec->channels)
channel = 0;
}
}
case PA_SAMPLE_FLOAT32NE: {
float *d;
int skip;
unsigned n;
unsigned channel;
for (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);
d = (float*) ((uint8_t*) c->memblock->data + c->index);
skip = spec->channels * sizeof(float);
n = c->length/sizeof(float)/spec->channels;
t *= volume;
t /= PA_VOLUME_NORM;
if (t < -0x8000) t = -0x8000;
if (t > 0x7FFF) t = 0x7FFF;
*d = (int16_t) t;
for (channel = 0; channel < spec->channels ; channel ++) {
float v, *t;
if (volume->values[channel] == PA_VOLUME_NORM)
continue;
v = (float) volume->values[channel] / PA_VOLUME_NORM;
t = d + channel;
oil_scalarmult_f32(t, skip, t, skip, &v, n);
}
}
} else if (spec->format == PA_SAMPLE_U8) {
uint8_t *d;
size_t n;
for (d = (uint8_t*) c->memblock->data + c->index, n = c->length; n > 0; d++, n--) {
int32_t t = (int32_t) *d - 0x80;
t *= volume;
t /= PA_VOLUME_NORM;
if (t < -0x80) t = -0x80;
if (t > 0x7F) t = 0x7F;
*d = (uint8_t) (t + 0x80);
}
} else if (spec->format == PA_SAMPLE_FLOAT32NE) {
float *d;
size_t n;
for (d = (float*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(float); n > 0; d++, n--) {
float t = *d;
t *= volume;
t /= PA_VOLUME_NORM;
if (t < -1) t = -1;
if (t > 1) t = 1;
*d = t;
}
} else {
abort();
default:
abort();
}
}

View file

@ -25,7 +25,7 @@
#include "sample.h"
#include "memblock.h"
#include "memchunk.h"
#include "volume.h"
pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec);
void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec);
@ -33,12 +33,21 @@ void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec);
typedef struct pa_mix_info {
pa_memchunk chunk;
pa_volume_t volume;
pa_cvolume volume;
void *userdata;
} pa_mix_info ;
} pa_mix_info;
size_t pa_mix(pa_mix_info channels[], unsigned nchannels, void *data, size_t length, const pa_sample_spec *spec, pa_volume_t volume);
size_t pa_mix(
const pa_mix_info channels[],
unsigned nchannels,
void *data,
size_t length,
const pa_sample_spec *spec,
const pa_cvolume *volume);
void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, pa_volume_t volume);
void pa_volume_memchunk(
pa_memchunk*c,
const pa_sample_spec *spec,
const pa_cvolume *volume);
#endif

View file

@ -30,29 +30,29 @@
#include "sample.h"
size_t pa_frame_size(const pa_sample_spec *spec) {
size_t b = 1;
size_t pa_sample_size(const pa_sample_spec *spec) {
assert(spec);
switch (spec->format) {
case PA_SAMPLE_U8:
case PA_SAMPLE_ULAW:
case PA_SAMPLE_ALAW:
b = 1;
break;
return 1;
case PA_SAMPLE_S16LE:
case PA_SAMPLE_S16BE:
b = 2;
break;
return 2;
case PA_SAMPLE_FLOAT32LE:
case PA_SAMPLE_FLOAT32BE:
b = 4;
break;
return 4;
default:
assert(0);
}
}
return b * spec->channels;
size_t pa_frame_size(const pa_sample_spec *spec) {
assert(spec);
return pa_sample_size(spec) * spec->channels;
}
size_t pa_bytes_per_second(const pa_sample_spec *spec) {
@ -69,10 +69,11 @@ pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec) {
int pa_sample_spec_valid(const pa_sample_spec *spec) {
assert(spec);
if (spec->rate <= 0 || spec->channels <= 0)
return 0;
if (spec->format >= PA_SAMPLE_MAX || spec->format < 0)
if (spec->rate <= 0 ||
spec->channels <= 0 ||
spec->channels > PA_CHANNELS_MAX ||
spec->format >= PA_SAMPLE_MAX ||
spec->format < 0)
return 0;
return 1;
@ -84,15 +85,15 @@ int pa_sample_spec_equal(const pa_sample_spec*a, const pa_sample_spec*b) {
return (a->format == b->format) && (a->rate == b->rate) && (a->channels == b->channels);
}
const char *pa_sample_format_to_string(pa_sample_format f) {
const char *pa_sample_format_to_string(pa_sample_format_t f) {
static const char* const table[]= {
[PA_SAMPLE_U8] = "U8",
[PA_SAMPLE_ALAW] = "ALAW",
[PA_SAMPLE_ULAW] = "ULAW",
[PA_SAMPLE_S16LE] = "S16LE",
[PA_SAMPLE_S16BE] = "S16BE",
[PA_SAMPLE_FLOAT32LE] = "FLOAT32LE",
[PA_SAMPLE_FLOAT32BE] = "FLOAT32BE",
[PA_SAMPLE_U8] = "u8",
[PA_SAMPLE_ALAW] = "aLaw",
[PA_SAMPLE_ULAW] = "uLaw",
[PA_SAMPLE_S16LE] = "s16le",
[PA_SAMPLE_S16BE] = "s16be",
[PA_SAMPLE_FLOAT32LE] = "float32le",
[PA_SAMPLE_FLOAT32BE] = "float32be",
};
if (f >= PA_SAMPLE_MAX)
@ -112,44 +113,6 @@ char *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) {
return s;
}
pa_volume_t pa_volume_multiply(pa_volume_t a, pa_volume_t b) {
uint64_t p = a;
p *= b;
p /= PA_VOLUME_NORM;
return (pa_volume_t) p;
}
pa_volume_t pa_volume_from_dB(double f) {
if (f <= PA_DECIBEL_MININFTY)
return PA_VOLUME_MUTED;
return (pa_volume_t) (pow(10, f/20)*PA_VOLUME_NORM);
}
double pa_volume_to_dB(pa_volume_t v) {
if (v == PA_VOLUME_MUTED)
return PA_DECIBEL_MININFTY;
return 20*log10((double) v/PA_VOLUME_NORM);
}
#define USER_DECIBEL_RANGE 30
double pa_volume_to_user(pa_volume_t v) {
double dB = pa_volume_to_dB(v);
return dB < -USER_DECIBEL_RANGE ? 0 : dB/USER_DECIBEL_RANGE+1;
}
pa_volume_t pa_volume_from_user(double v) {
if (v <= 0)
return PA_VOLUME_MUTED;
return pa_volume_from_dB((v-1)*USER_DECIBEL_RANGE);
}
void pa_bytes_snprint(char *s, size_t l, unsigned v) {
if (v >= ((unsigned) 1024)*1024*1024)
snprintf(s, l, "%0.1f GB", ((double) v)/1024/1024/1024);
@ -161,7 +124,7 @@ void pa_bytes_snprint(char *s, size_t l, unsigned v) {
snprintf(s, l, "%u B", (unsigned) v);
}
pa_sample_format pa_parse_sample_format(const char *format) {
pa_sample_format_t pa_parse_sample_format(const char *format) {
if (strcasecmp(format, "s16le") == 0)
return PA_SAMPLE_S16LE;

View file

@ -33,6 +33,9 @@
PA_C_DECL_BEGIN
/* Maximum allowed channels */
#define PA_CHANNELS_MAX 16
/** Sample format */
typedef enum pa_sample_format {
PA_SAMPLE_U8, /**< Unsigned 8 Bit PCM */
@ -44,7 +47,7 @@ typedef enum pa_sample_format {
PA_SAMPLE_FLOAT32BE, /**< 32 Bit IEEE floating point, big endian, range -1..1 */
PA_SAMPLE_MAX, /**< Upper limit of valid sample types */
PA_SAMPLE_INVALID = -1 /**< An invalid value */
} pa_sample_format;
} pa_sample_format_t;
#ifdef WORDS_BIGENDIAN
/** Signed 16 Bit PCM, native endian */
@ -71,7 +74,7 @@ typedef enum pa_sample_format {
/** A sample format and attribute specification */
typedef struct pa_sample_spec {
pa_sample_format format; /**< The sample format */
pa_sample_format_t format; /**< The sample format */
uint32_t rate; /**< The sample rate. (e.g. 44100) */
uint8_t channels; /**< Audio channels. (1 for mono, 2 for stereo, ...) */
} pa_sample_spec;
@ -85,6 +88,9 @@ size_t pa_bytes_per_second(const pa_sample_spec *spec);
/** Return the size of a frame with the specific sample type */
size_t pa_frame_size(const pa_sample_spec *spec);
/** Return the size of a sample with the specific sample type */
size_t pa_sample_size(const pa_sample_spec *spec);
/** Calculate the time the specified bytes take to play with the specified sample type */
pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec);
@ -95,7 +101,10 @@ int pa_sample_spec_valid(const pa_sample_spec *spec);
int pa_sample_spec_equal(const pa_sample_spec*a, const pa_sample_spec*b);
/* Return a descriptive string for the specified sample format. \since 0.8 */
const char *pa_sample_format_to_string(pa_sample_format f);
const char *pa_sample_format_to_string(pa_sample_format_t f);
/** Parse a sample format text. Inverse of pa_sample_format_to_string() */
pa_sample_format_t pa_parse_sample_format(const char *format);
/** Maximum required string length for pa_sample_spec_snprint() */
#define PA_SAMPLE_SPEC_SNPRINT_MAX 32
@ -103,43 +112,9 @@ const char *pa_sample_format_to_string(pa_sample_format f);
/** Pretty print a sample type specification to a string */
char* pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec);
/** Volume specification: 0: silence; < 256: diminished volume; 256: normal volume; > 256 amplified volume */
typedef uint32_t pa_volume_t;
/** Normal volume (100%) */
#define PA_VOLUME_NORM (0x100)
/** Muted volume (0%) */
#define PA_VOLUME_MUTED (0)
/** Multiply two volumes specifications, return the result. This uses PA_VOLUME_NORM as neutral element of multiplication. */
pa_volume_t pa_volume_multiply(pa_volume_t a, pa_volume_t b);
/** Convert volume from decibel to linear level. \since 0.4 */
pa_volume_t pa_volume_from_dB(double f);
/** Convert volume from linear level to decibel. \since 0.4 */
double pa_volume_to_dB(pa_volume_t v);
/** Convert volume to scaled value understandable by the user (between 0 and 1). \since 0.6 */
double pa_volume_to_user(pa_volume_t v);
/** Convert user volume to polypaudio volume. \since 0.6 */
pa_volume_t pa_volume_from_user(double v);
#ifdef INFINITY
#define PA_DECIBEL_MININFTY (-INFINITY)
#else
/** This value is used as minus infinity when using pa_volume_{to,from}_dB(). \since 0.4 */
#define PA_DECIBEL_MININFTY (-200)
#endif
/** Pretty print a byte size value. (i.e. "2.5 MB") */
void pa_bytes_snprint(char *s, size_t l, unsigned v);
/** Parse a sample format text. Inverse of pa_sample_format_to_string() */
pa_sample_format pa_parse_sample_format(const char *format);
PA_C_DECL_END
#endif

View file

@ -52,6 +52,8 @@
#include "sound-file.h"
#include "util.h"
#include "log.h"
#include "channelmap.h"
#include "volume.h"
#define UNLOAD_POLL_TIME 2
@ -112,7 +114,7 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE|PA_SUBSCRIPTION_EVENT_NEW, e->index);
}
e->volume = PA_VOLUME_NORM;
pa_cvolume_reset(&e->volume, PA_CHANNELS_MAX);
e->last_used_time = 0;
e->memchunk.memblock = NULL;
e->memchunk.index = e->memchunk.length = 0;
@ -125,15 +127,20 @@ static pa_scache_entry* scache_add_item(pa_core *c, const char *name) {
return e;
}
int pa_scache_add_item(pa_core *c, const char *name, pa_sample_spec *ss, pa_memchunk *chunk, uint32_t *idx) {
int pa_scache_add_item(pa_core *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map, const pa_memchunk *chunk, uint32_t *idx) {
pa_scache_entry *e;
assert(c && name);
if (!(e = scache_add_item(c, name)))
return -1;
if (ss)
if (ss) {
e->sample_spec = *ss;
pa_channel_map_init_auto(&e->channel_map, ss->channels);
}
if (map)
e->channel_map = *map;
if (chunk) {
e->memchunk = *chunk;
@ -161,7 +168,7 @@ int pa_scache_add_file(pa_core *c, const char *name, const char *filename, uint3
if (pa_sound_file_load(filename, &ss, &chunk, c->memblock_stat) < 0)
return -1;
r = pa_scache_add_item(c, name, &ss, &chunk, idx);
r = pa_scache_add_item(c, name, &ss, NULL, &chunk, idx);
pa_memblock_unref(chunk.memblock);
return r;
@ -230,9 +237,10 @@ void pa_scache_free(pa_core *c) {
c->mainloop->time_free(c->scache_auto_unload_event);
}
int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, uint32_t volume) {
int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, const pa_cvolume *volume) {
pa_scache_entry *e;
char *t;
pa_cvolume r;
assert(c && name && sink);
if (!(e = pa_namereg_get(c, name, PA_NAMEREG_SAMPLE, 1)))
@ -249,7 +257,8 @@ int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, uint32_t vo
return -1;
t = pa_sprintf_malloc("sample:%s", name);
if (pa_play_memchunk(sink, t, &e->sample_spec, &e->memchunk, pa_volume_multiply(volume, e->volume)) < 0) {
if (pa_play_memchunk(sink, t, &e->sample_spec, &e->channel_map, &e->memchunk, pa_sw_cvolume_multiply(&r, volume, &e->volume)) < 0) {
free(t);
return -1;
}

View file

@ -31,8 +31,9 @@ typedef struct pa_scache_entry {
uint32_t index;
char *name;
uint32_t volume;
pa_cvolume volume;
pa_sample_spec sample_spec;
pa_channel_map channel_map;
pa_memchunk memchunk;
char *filename;
@ -41,14 +42,14 @@ typedef struct pa_scache_entry {
time_t last_used_time;
} pa_scache_entry;
int pa_scache_add_item(pa_core *c, const char *name, pa_sample_spec *ss, pa_memchunk *chunk, uint32_t *idx);
int pa_scache_add_item(pa_core *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map, const pa_memchunk *chunk, uint32_t *idx);
int pa_scache_add_file(pa_core *c, const char *name, const char *filename, uint32_t *idx);
int pa_scache_add_file_lazy(pa_core *c, const char *name, const char *filename, uint32_t *idx);
int pa_scache_add_directory_lazy(pa_core *c, const char *pathname);
int pa_scache_remove_item(pa_core *c, const char *name);
int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, uint32_t volume);
int pa_scache_play_item(pa_core *c, const char *name, pa_sink *sink, const pa_cvolume *cvolume);
void pa_scache_free(pa_core *c);
const char *pa_scache_get_name_by_id(pa_core *c, uint32_t id);

View file

@ -23,11 +23,19 @@
#include <config.h>
#endif
#include "endianmacros.h"
#define INT16_FROM INT16_FROM_BE
#define INT16_TO INT16_TO_BE
#define pa_sconv_s16le_to_float32ne pa_sconv_s16be_to_float32ne
#define pa_sconv_s16le_from_float32ne pa_sconv_s16be_from_float32ne
#ifdef WORDS_BIGENDIAN
#define SWAP_WORDS 0
#else
#define SWAP_WORDS 1
#endif
#include "sconv-s16le.h"
#include "sconv-s16le.c"

View file

@ -22,7 +22,7 @@
USA.
***/
void pa_sconv_s16be_to_float32ne(unsigned n, const void *a, unsigned an, float *b);
void pa_sconv_s16be_from_float32ne(unsigned n, const float *a, void *b, unsigned bn);
void pa_sconv_s16be_to_float32ne(unsigned n, const void *a, float *b);
void pa_sconv_s16be_from_float32ne(unsigned n, const float *a, void *b);
#endif

View file

@ -26,6 +26,8 @@
#include <assert.h>
#include <inttypes.h>
#include <liboil/liboilfuncs.h>
#include "endianmacros.h"
#include "sconv.h"
#include "sconv-s16le.h"
@ -39,49 +41,61 @@
#define INT16_TO INT16_TO_LE
#endif
void pa_sconv_s16le_to_float32ne(unsigned n, const void *a, unsigned an, float *b) {
#ifndef SWAP_WORDS
#ifdef WORDS_BIGENDIAN
#define SWAP_WORDS 1
#else
#define SWAP_WORDS 0
#endif
#endif
void pa_sconv_s16le_to_float32ne(unsigned n, const void *a, float *b) {
const int16_t *ca = a;
assert(n && a && an && b);
assert(a);
assert(b);
#if SWAP_WORDS == 1
for (; n > 0; n--) {
unsigned i;
float sum = 0;
for (i = 0; i < an; i++) {
int16_t s = *(ca++);
sum += ((float) INT16_FROM(s))/0x7FFF;
}
if (sum > 1)
sum = 1;
if (sum < -1)
sum = -1;
*(b++) = sum;
int16_t s = *(ca++);
*(b++) = ((float) INT16_FROM(s))/0x7FFF;
}
#else
{
static const double add = 0, factor = 1.0/0x7FFF;
oil_scaleconv_f32_s16(b, ca, n, &add, &factor);
}
#endif
}
void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b, unsigned bn) {
void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b) {
int16_t *cb = b;
/* pa_log("%u %p %p %u\n", n, a, b, bn); */
assert(n && a && b && bn);
assert(a);
assert(b);
#if SWAP_WORDS == 1
for (; n > 0; n--) {
unsigned i;
int16_t s;
float v = *(a++);
if (v > 1)
v = 1;
if (v < -1)
v = -1;
s = (int16_t) (v * 0x7FFF);
s = INT16_TO(s);
for (i = 0; i < bn; i++)
*(cb++) = s;
*(cb++) = INT16_TO(s);
}
#else
{
static const double add = 0, factor = 0x7FFF;
oil_scaleconv_s16_f32(cb, a, n, &add, &factor);
}
#endif
}

View file

@ -22,7 +22,7 @@
USA.
***/
void pa_sconv_s16le_to_float32ne(unsigned n, const void *a, unsigned an, float *b);
void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b, unsigned bn);
void pa_sconv_s16le_to_float32ne(unsigned n, const void *a, float *b);
void pa_sconv_s16le_from_float32ne(unsigned n, const float *a, void *b);
#endif

View file

@ -26,6 +26,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <liboil/liboilfuncs.h>
#include <liboil/liboil.h>
#include "endianmacros.h"
#include "sconv.h"
#include "g711.h"
@ -33,107 +37,58 @@
#include "sconv-s16le.h"
#include "sconv-s16be.h"
static void u8_to_float32ne(unsigned n, const void *a, unsigned an, float *b) {
unsigned i;
static void u8_to_float32ne(unsigned n, const void *a, float *b) {
const uint8_t *ca = a;
assert(n && a && an && b);
static const double add = -128.0/127.0, factor = 1.0/127.0;
assert(a);
assert(b);
for (; n > 0; n--) {
float sum = 0;
for (i = 0; i < an; i++) {
uint8_t v = *(ca++);
sum += (((float) v)-128)/127;
}
if (sum > 1)
sum = 1;
if (sum < -1)
sum = -1;
*(b++) = sum;
}
oil_scaleconv_f32_u8(b, ca, n, &add, &factor);
}
static void u8_from_float32ne(unsigned n, const float *a, void *b, unsigned bn) {
unsigned i;
static void u8_from_float32ne(unsigned n, const float *a, void *b) {
uint8_t *cb = b;
static const double add = 128.0, factor = 127.0;
assert(n && a && b && bn);
for (; n > 0; n--) {
float v = *(a++);
uint8_t u;
assert(a);
assert(b);
if (v > 1)
v = 1;
if (v < -1)
v = -1;
u = (uint8_t) (v*127+128);
for (i = 0; i < bn; i++)
*(cb++) = u;
}
oil_scaleconv_u8_f32(cb, a, n, &add, &factor);
}
static void float32ne_to_float32ne(unsigned n, const void *a, unsigned an, float *b) {
unsigned i;
const float *ca = a;
assert(n && a && an && b);
for (; n > 0; n--) {
float sum = 0;
static void float32ne_to_float32ne(unsigned n, const void *a, float *b) {
assert(a);
assert(b);
for (i = 0; i < an; i++)
sum += *(ca++);
if (sum > 1)
sum = 1;
if (sum < -1)
sum = -1;
*(b++) = sum;
}
oil_memcpy(b, a, sizeof(float) * n);
}
static void float32ne_from_float32ne(unsigned n, const float *a, void *b, unsigned bn) {
unsigned i;
float *cb = b;
assert(n && a && b && bn);
for (; n > 0; n--) {
float v = *(a++);
for (i = 0; i < bn; i++)
*(cb++) = v;
}
static void float32ne_from_float32ne(unsigned n, const float *a, void *b) {
assert(a);
assert(b);
oil_memcpy(b, a, sizeof(float) * n);
}
static void ulaw_to_float32ne(unsigned n, const void *a, unsigned an, float *b) {
unsigned i;
static void ulaw_to_float32ne(unsigned n, const void *a, float *b) {
const uint8_t *ca = a;
assert(n && a && an && b);
for (; n > 0; n--) {
float sum = 0;
for (i = 0; i < an; i++)
sum += st_ulaw2linear16(*ca++) * 1.0F / 0x7FFF;
if (sum > 1)
sum = 1;
if (sum < -1)
sum = -1;
*(b++) = sum;
}
assert(a);
assert(b);
for (; n > 0; n--)
*(b++) = st_ulaw2linear16(*(ca++)) * 1.0F / 0x7FFF;
}
static void ulaw_from_float32ne(unsigned n, const float *a, void *b, unsigned bn) {
unsigned i;
static void ulaw_from_float32ne(unsigned n, const float *a, void *b) {
uint8_t *cb = b;
assert(n && a && b && bn);
assert(a);
assert(b);
for (; n > 0; n--) {
float v = *(a++);
uint8_t u;
if (v > 1)
v = 1;
@ -141,40 +96,28 @@ static void ulaw_from_float32ne(unsigned n, const float *a, void *b, unsigned bn
if (v < -1)
v = -1;
u = st_14linear2ulaw((int16_t) (v * 0x1FFF));
for (i = 0; i < bn; i++)
*(cb++) = u;
*(cb++) = st_14linear2ulaw((int16_t) (v * 0x1FFF));
}
}
static void alaw_to_float32ne(unsigned n, const void *a, unsigned an, float *b) {
unsigned i;
static void alaw_to_float32ne(unsigned n, const void *a, float *b) {
const uint8_t *ca = a;
assert(n && a && an && b);
for (; n > 0; n--) {
float sum = 0;
for (i = 0; i < an; i++)
sum += st_alaw2linear16(*ca++) * 1.0F / 0x7FFF;
assert(a);
assert(b);
if (sum > 1)
sum = 1;
if (sum < -1)
sum = -1;
*(b++) = sum;
}
for (; n > 0; n--)
*(b++) = st_alaw2linear16(*(ca++)) * 1.0F / 0x7FFF;
}
static void alaw_from_float32ne(unsigned n, const float *a, void *b, unsigned bn) {
unsigned i;
static void alaw_from_float32ne(unsigned n, const float *a, void *b) {
uint8_t *cb = b;
assert(n && a && b && bn);
assert(a);
assert(b);
for (; n > 0; n--) {
float v = *(a++);
uint8_t u;
if (v > 1)
v = 1;
@ -182,15 +125,11 @@ static void alaw_from_float32ne(unsigned n, const float *a, void *b, unsigned bn
if (v < -1)
v = -1;
u = st_13linear2alaw((int16_t) (v * 0xFFF));
for (i = 0; i < bn; i++)
*(cb++) = u;
*(cb++) = st_13linear2alaw((int16_t) (v * 0xFFF));
}
}
pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_format f) {
pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_format_t f) {
switch(f) {
case PA_SAMPLE_U8:
return u8_to_float32ne;
@ -209,7 +148,7 @@ pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_fo
}
}
pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(pa_sample_format f) {
pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(pa_sample_format_t f) {
switch(f) {
case PA_SAMPLE_U8:
return u8_from_float32ne;

View file

@ -24,10 +24,10 @@
#include "sample.h"
typedef void (*pa_convert_to_float32ne_func_t)(unsigned n, const void *a, unsigned an, float *b);
typedef void (*pa_convert_from_float32ne_func_t)(unsigned n, const float *a, void *b, unsigned bn);
typedef void (*pa_convert_to_float32ne_func_t)(unsigned n, const void *a, float *b);
typedef void (*pa_convert_from_float32ne_func_t)(unsigned n, const float *a, void *b);
pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_format f);
pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(pa_sample_format f);
pa_convert_to_float32ne_func_t pa_get_convert_to_float32ne_function(pa_sample_format_t f);
pa_convert_from_float32ne_func_t pa_get_convert_from_float32ne_function(pa_sample_format_t f);
#endif

View file

@ -36,47 +36,66 @@
#define CONVERT_BUFFER_LENGTH 4096
pa_sink_input* pa_sink_input_new(pa_sink *s, pa_typeid_t typeid, const char *name, const pa_sample_spec *spec, int variable_rate, int resample_method) {
pa_sink_input* pa_sink_input_new(
pa_sink *s,
const char *driver,
const char *name,
const pa_sample_spec *spec,
const pa_channel_map *map,
int variable_rate,
int resample_method) {
pa_sink_input *i;
pa_resampler *resampler = NULL;
int r;
char st[256];
assert(s && spec && s->state == PA_SINK_RUNNING);
pa_channel_map tmap;
assert(s);
assert(spec);
assert(s->state == PA_SINK_RUNNING);
if (pa_idxset_size(s->inputs) >= PA_MAX_INPUTS_PER_SINK) {
pa_log(__FILE__": Failed to create sink input: too many inputs per sink.\n");
pa_log_warn(__FILE__": Failed to create sink input: too many inputs per sink.\n");
return NULL;
}
if (resample_method == PA_RESAMPLER_INVALID)
resample_method = s->core->resample_method;
if (variable_rate || !pa_sample_spec_equal(spec, &s->sample_spec))
if (!(resampler = pa_resampler_new(spec, &s->sample_spec, s->core->memblock_stat, resample_method)))
if (!map) {
pa_channel_map_init_auto(&tmap, spec->channels);
map = &tmap;
}
if (variable_rate || !pa_sample_spec_equal(spec, &s->sample_spec) || !pa_channel_map_equal(map, &s->channel_map))
if (!(resampler = pa_resampler_new(spec, map, &s->sample_spec, &s->channel_map, s->core->memblock_stat, resample_method)))
return NULL;
i = pa_xmalloc(sizeof(pa_sink_input));
i = pa_xnew(pa_sink_input, 1);
i->ref = 1;
i->state = PA_SINK_INPUT_RUNNING;
i->name = pa_xstrdup(name);
i->typeid = typeid;
i->client = NULL;
i->driver = pa_xstrdup(driver);
i->owner = NULL;
i->sink = s;
i->sample_spec = *spec;
i->client = NULL;
i->sample_spec = *spec;
i->channel_map = *map;
pa_cvolume_reset(&i->volume, spec->channels);
i->peek = NULL;
i->drop = NULL;
i->kill = NULL;
i->get_latency = NULL;
i->userdata = NULL;
i->underrun = NULL;
i->userdata = NULL;
i->volume = PA_VOLUME_NORM;
i->playing = 0;
i->resampled_chunk.memblock = NULL;
i->resampled_chunk.index = i->resampled_chunk.length = 0;
pa_memchunk_reset(&i->resampled_chunk);
i->resampler = resampler;
assert(s->core);
@ -94,7 +113,10 @@ pa_sink_input* pa_sink_input_new(pa_sink *s, pa_typeid_t typeid, const char *nam
}
void pa_sink_input_disconnect(pa_sink_input *i) {
assert(i && i->state != PA_SINK_INPUT_DISCONNECTED && i->sink && i->sink->core);
assert(i);
assert(i->state != PA_SINK_INPUT_DISCONNECTED);
assert(i->sink);
assert(i->sink->core);
pa_idxset_remove_by_data(i->sink->core->sink_inputs, i, NULL);
pa_idxset_remove_by_data(i->sink->inputs, i, NULL);
@ -106,7 +128,9 @@ void pa_sink_input_disconnect(pa_sink_input *i) {
i->drop = NULL;
i->kill = NULL;
i->get_latency = NULL;
i->underrun = NULL;
i->playing = 0;
i->state = PA_SINK_INPUT_DISCONNECTED;
}
@ -120,28 +144,34 @@ static void sink_input_free(pa_sink_input* i) {
if (i->resampled_chunk.memblock)
pa_memblock_unref(i->resampled_chunk.memblock);
if (i->resampler)
pa_resampler_free(i->resampler);
pa_xfree(i->name);
pa_xfree(i->driver);
pa_xfree(i);
}
void pa_sink_input_unref(pa_sink_input *i) {
assert(i && i->ref >= 1);
assert(i);
assert(i->ref >= 1);
if (!(--i->ref))
sink_input_free(i);
}
pa_sink_input* pa_sink_input_ref(pa_sink_input *i) {
assert(i && i->ref >= 1);
assert(i);
assert(i->ref >= 1);
i->ref++;
return i;
}
void pa_sink_input_kill(pa_sink_input*i) {
assert(i && i->ref >= 1);
assert(i);
assert(i->ref >= 1);
if (i->kill)
i->kill(i);
@ -149,7 +179,9 @@ void pa_sink_input_kill(pa_sink_input*i) {
pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) {
pa_usec_t r = 0;
assert(i && i->ref >= 1);
assert(i);
assert(i->ref >= 1);
if (i->get_latency)
r += i->get_latency(i);
@ -160,20 +192,28 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) {
return r;
}
int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) {
int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) {
int ret = -1;
assert(i && chunk && i->ref >= 1);
int do_volume_adj_here;
assert(i);
assert(i->ref >= 1);
assert(chunk);
assert(volume);
pa_sink_input_ref(i);
if (!i->peek || !i->drop || i->state == PA_SINK_INPUT_CORKED)
goto finish;
if (!i->resampler) {
do_volume_adj_here = 0;
ret = i->peek(i, chunk);
goto finish;
}
do_volume_adj_here = !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map);
while (!i->resampled_chunk.memblock) {
pa_memchunk tchunk;
size_t l;
@ -182,6 +222,12 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) {
goto finish;
assert(tchunk.length);
/* It might be necessary to adjust the volume here */
if (do_volume_adj_here) {
pa_memchunk_make_writable(&tchunk, i->sink->core->memblock_stat, 0);
pa_volume_memchunk(&tchunk, &i->sample_spec, &i->volume);
}
l = pa_resampler_request(i->resampler, CONVERT_BUFFER_LENGTH);
@ -195,7 +241,9 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk) {
pa_memblock_unref(tchunk.memblock);
}
assert(i->resampled_chunk.memblock && i->resampled_chunk.length);
assert(i->resampled_chunk.memblock);
assert(i->resampled_chunk.length);
*chunk = i->resampled_chunk;
pa_memblock_ref(i->resampled_chunk.memblock);
@ -207,6 +255,19 @@ finish:
i->underrun(i);
i->playing = ret >= 0;
if (ret >= 0) {
/* Let's see if we had to apply the volume adjustment
* ourselves, or if this can be done by the sink for us */
if (do_volume_adj_here)
/* We've both the same channel map, so let's have the sink do the adjustment for us*/
pa_cvolume_reset(volume, i->sample_spec.channels);
else
/* We had different channel maps, so we already did the adjustment */
*volume = i->volume;
}
pa_sink_input_unref(i);
@ -214,7 +275,9 @@ finish:
}
void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t length) {
assert(i && length && i->ref >= 1);
assert(i);
assert(i->ref >= 1);
assert(length > 0);
if (!i->resampler) {
if (i->drop)
@ -222,35 +285,50 @@ void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t lengt
return;
}
assert(i->resampled_chunk.memblock && i->resampled_chunk.length >= length);
assert(i->resampled_chunk.memblock);
assert(i->resampled_chunk.length >= length);
i->resampled_chunk.index += length;
i->resampled_chunk.length -= length;
if (!i->resampled_chunk.length) {
if (i->resampled_chunk.length <= 0) {
pa_memblock_unref(i->resampled_chunk.memblock);
i->resampled_chunk.memblock = NULL;
i->resampled_chunk.index = i->resampled_chunk.length = 0;
}
}
void pa_sink_input_set_volume(pa_sink_input *i, pa_volume_t volume) {
assert(i && i->sink && i->sink->core && i->ref >= 1);
void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume) {
assert(i);
assert(i->ref >= 1);
assert(i->sink);
assert(i->sink->core);
if (i->volume != volume) {
i->volume = volume;
pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
}
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);
}
const pa_cvolume * pa_sink_input_get_volume(pa_sink_input *i) {
assert(i);
assert(i->ref >= 1);
return &i->volume;
}
void pa_sink_input_cork(pa_sink_input *i, int b) {
int n;
assert(i && i->ref >= 1);
assert(i);
assert(i->ref >= 1);
if (i->state == PA_SINK_INPUT_DISCONNECTED)
return;
n = i->state == PA_SINK_INPUT_CORKED && !b;
i->state = b ? PA_SINK_INPUT_CORKED : PA_SINK_INPUT_RUNNING;
if (n)
@ -258,7 +336,9 @@ void pa_sink_input_cork(pa_sink_input *i, int b) {
}
void pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) {
assert(i && i->resampler && i->ref >= 1);
assert(i);
assert(i->resampler);
assert(i->ref >= 1);
if (i->sample_spec.rate == rate)
return;
@ -268,7 +348,8 @@ void pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate) {
}
void pa_sink_input_set_name(pa_sink_input *i, const char *name) {
assert(i && i->ref >= 1);
assert(i);
assert(i->ref >= 1);
pa_xfree(i->name);
i->name = pa_xstrdup(name);
@ -276,8 +357,9 @@ void pa_sink_input_set_name(pa_sink_input *i, const char *name) {
pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
}
pa_resample_method pa_sink_input_get_resample_method(pa_sink_input *i) {
assert(i && i->ref >= 1);
pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i) {
assert(i);
assert(i->ref >= 1);
if (!i->resampler)
return PA_RESAMPLER_INVALID;

View file

@ -33,25 +33,27 @@ typedef struct pa_sink_input pa_sink_input;
#include "module.h"
#include "client.h"
typedef enum {
typedef enum pa_sink_input_state {
PA_SINK_INPUT_RUNNING,
PA_SINK_INPUT_CORKED,
PA_SINK_INPUT_DISCONNECTED
} pa_sink_input_state ;
} pa_sink_input_state_t;
struct pa_sink_input {
int ref;
pa_sink_input_state state;
uint32_t index;
pa_typeid_t typeid;
char *name;
pa_sink_input_state_t state;
char *name, *driver;
pa_module *owner;
pa_client *client;
pa_sink *sink;
pa_client *client;
pa_sample_spec sample_spec;
uint32_t volume;
pa_channel_map channel_map;
pa_cvolume volume;
int (*peek) (pa_sink_input *i, pa_memchunk *chunk);
void (*drop) (pa_sink_input *i, const pa_memchunk *chunk, size_t length);
@ -67,7 +69,15 @@ struct pa_sink_input {
pa_resampler *resampler;
};
pa_sink_input* pa_sink_input_new(pa_sink *s, pa_typeid_t typeid, const char *name, const pa_sample_spec *spec, int variable_rate, int resample_method);
pa_sink_input* pa_sink_input_new(
pa_sink *s,
const char *driver,
const char *name,
const pa_sample_spec *spec,
const pa_channel_map *map,
int variable_rate,
int resample_method);
void pa_sink_input_unref(pa_sink_input* i);
pa_sink_input* pa_sink_input_ref(pa_sink_input* i);
@ -79,10 +89,11 @@ void pa_sink_input_kill(pa_sink_input*i);
pa_usec_t pa_sink_input_get_latency(pa_sink_input *i);
int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk);
int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume);
void pa_sink_input_drop(pa_sink_input *i, const pa_memchunk *chunk, size_t length);
void pa_sink_input_set_volume(pa_sink_input *i, pa_volume_t volume);
void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume);
const pa_cvolume * pa_sink_input_get_volume(pa_sink_input *i);
void pa_sink_input_cork(pa_sink_input *i, int b);
@ -90,6 +101,6 @@ void pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate);
void pa_sink_input_set_name(pa_sink_input *i, const char *name);
pa_resample_method pa_sink_input_get_resample_method(pa_sink_input *i);
pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i);
#endif

View file

@ -40,43 +40,54 @@
#define MAX_MIX_CHANNELS 32
pa_sink* pa_sink_new(pa_core *core, pa_typeid_t typeid, const char *name, int fail, const pa_sample_spec *spec) {
pa_sink* pa_sink_new(
pa_core *core,
const char *driver,
const char *name,
int fail,
const pa_sample_spec *spec,
const pa_channel_map *map) {
pa_sink *s;
char *n = NULL;
char st[256];
int r;
assert(core && name && *name && spec);
s = pa_xmalloc(sizeof(pa_sink));
assert(core);
assert(name);
assert(*name);
assert(spec);
s = pa_xnew(pa_sink, 1);
if (!(name = pa_namereg_register(core, name, PA_NAMEREG_SINK, s, fail))) {
pa_xfree(s);
return NULL;
}
s->ref = 1;
s->core = core;
s->state = PA_SINK_RUNNING;
s->name = pa_xstrdup(name);
s->description = NULL;
s->typeid = typeid;
s->ref = 1;
s->state = PA_SINK_RUNNING;
s->driver = pa_xstrdup(driver);
s->owner = NULL;
s->core = core;
s->sample_spec = *spec;
if (map)
s->channel_map = *map;
else
pa_channel_map_init_auto(&s->channel_map, spec->channels);
s->inputs = pa_idxset_new(NULL, NULL);
n = pa_sprintf_malloc("%s_monitor", name);
s->monitor_source = pa_source_new(core, typeid, n, 0, spec);
assert(s->monitor_source);
pa_xfree(n);
s->monitor_source->monitor_of = s;
s->monitor_source->description = pa_sprintf_malloc("Monitor source of sink '%s'", s->name);
s->volume = PA_VOLUME_NORM;
pa_cvolume_reset(&s->sw_volume, spec->channels);
pa_cvolume_reset(&s->hw_volume, spec->channels);
s->notify = NULL;
s->get_latency = NULL;
s->notify = NULL;
s->set_hw_volume = NULL;
s->get_hw_volume = NULL;
s->userdata = NULL;
r = pa_idxset_put(core->sinks, s, &s->index);
@ -85,6 +96,13 @@ pa_sink* pa_sink_new(pa_core *core, pa_typeid_t typeid, const char *name, int fa
pa_sample_spec_snprint(st, sizeof(st), spec);
pa_log_info(__FILE__": created %u \"%s\" with sample spec \"%s\"\n", s->index, s->name, st);
n = pa_sprintf_malloc("%s_monitor", name);
s->monitor_source = pa_source_new(core, driver, n, 0, spec, map);
assert(s->monitor_source);
pa_xfree(n);
s->monitor_source->monitor_of = s;
s->monitor_source->description = pa_sprintf_malloc("Monitor source of sink '%s'", s->name);
pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_NEW, s->index);
return s;
@ -92,7 +110,9 @@ pa_sink* pa_sink_new(pa_core *core, pa_typeid_t typeid, const char *name, int fa
void pa_sink_disconnect(pa_sink* s) {
pa_sink_input *i, *j = NULL;
assert(s && s->state == PA_SINK_RUNNING);
assert(s);
assert(s->state == PA_SINK_RUNNING);
pa_namereg_unregister(s->core, s->name);
@ -105,16 +125,19 @@ void pa_sink_disconnect(pa_sink* s) {
pa_source_disconnect(s->monitor_source);
pa_idxset_remove_by_data(s->core->sinks, s, NULL);
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
s->notify = NULL;
s->get_latency = NULL;
s->notify = NULL;
s->get_hw_volume = NULL;
s->set_hw_volume = NULL;
s->state = PA_SINK_DISCONNECTED;
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_REMOVE, s->index);
}
static void sink_free(pa_sink *s) {
assert(s && s->ref == 0);
assert(s);
assert(!s->ref);
if (s->state != PA_SINK_DISCONNECTED)
pa_sink_disconnect(s);
@ -128,24 +151,29 @@ static void sink_free(pa_sink *s) {
pa_xfree(s->name);
pa_xfree(s->description);
pa_xfree(s->driver);
pa_xfree(s);
}
void pa_sink_unref(pa_sink*s) {
assert(s && s->ref >= 1);
assert(s);
assert(s->ref >= 1);
if (!(--s->ref))
sink_free(s);
}
pa_sink* pa_sink_ref(pa_sink *s) {
assert(s && s->ref >= 1);
assert(s);
assert(s->ref >= 1);
s->ref++;
return s;
}
void pa_sink_notify(pa_sink*s) {
assert(s && s->ref >= 1);
assert(s);
assert(s->ref >= 1);
if (s->notify)
s->notify(s);
@ -156,20 +184,25 @@ static unsigned fill_mix_info(pa_sink *s, pa_mix_info *info, unsigned maxinfo) {
pa_sink_input *i;
unsigned n = 0;
assert(s && s->ref >= 1 && info);
assert(s);
assert(s->ref >= 1);
assert(info);
for (i = pa_idxset_first(s->inputs, &idx); maxinfo > 0 && i; i = pa_idxset_next(s->inputs, &idx)) {
/* Increase ref counter, to make sure that this input doesn't
* vanish while we still need it */
pa_sink_input_ref(i);
if (pa_sink_input_peek(i, &info->chunk) < 0) {
if (pa_sink_input_peek(i, &info->chunk, &info->volume) < 0) {
pa_sink_input_unref(i);
continue;
}
info->volume = i->volume;
info->userdata = i;
assert(info->chunk.memblock && info->chunk.memblock->data && info->chunk.length);
assert(info->chunk.memblock);
assert(info->chunk.memblock->data);
assert(info->chunk.length);
info++;
maxinfo--;
@ -180,15 +213,21 @@ static unsigned fill_mix_info(pa_sink *s, pa_mix_info *info, unsigned maxinfo) {
}
static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned maxinfo, size_t length) {
assert(s && s->ref >= 1 && info);
assert(s);
assert(s->ref >= 1);
assert(info);
for (; maxinfo > 0; maxinfo--, info++) {
pa_sink_input *i = info->userdata;
assert(i && info->chunk.memblock);
assert(i);
assert(info->chunk.memblock);
/* Drop read data */
pa_sink_input_drop(i, &info->chunk, length);
pa_memblock_unref(info->chunk.memblock);
/* Decrease ref counter */
pa_sink_input_unref(i);
info->userdata = NULL;
}
@ -197,8 +236,8 @@ static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned maxinfo, size_t
int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
pa_mix_info info[MAX_MIX_CHANNELS];
unsigned n;
size_t l;
int r = -1;
assert(s);
assert(s->ref >= 1);
assert(length);
@ -212,37 +251,29 @@ int pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) {
goto finish;
if (n == 1) {
uint32_t volume = PA_VOLUME_NORM;
pa_sink_input *i = info[0].userdata;
assert(i);
pa_cvolume volume;
*result = info[0].chunk;
pa_memblock_ref(result->memblock);
if (result->length > length)
result->length = length;
l = result->length;
if (s->volume != PA_VOLUME_NORM || info[0].volume != PA_VOLUME_NORM)
volume = pa_volume_multiply(s->volume, info[0].volume);
pa_sw_cvolume_multiply(&volume, &s->sw_volume, &info[0].volume);
if (volume != PA_VOLUME_NORM) {
if (!pa_cvolume_is_norm(&volume)) {
pa_memchunk_make_writable(result, s->core->memblock_stat, 0);
pa_volume_memchunk(result, &s->sample_spec, volume);
pa_volume_memchunk(result, &s->sample_spec, &volume);
}
} else {
result->memblock = pa_memblock_new(length, s->core->memblock_stat);
assert(result->memblock);
result->length = l = pa_mix(info, n, result->memblock->data, length, &s->sample_spec, s->volume);
result->length = pa_mix(info, n, result->memblock->data, length, &s->sample_spec, &s->sw_volume);
result->index = 0;
assert(l);
}
inputs_drop(s, info, n, l);
assert(s->monitor_source);
inputs_drop(s, info, n, result->length);
pa_source_post(s->monitor_source, result);
r = 0;
@ -256,9 +287,14 @@ finish:
int pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
pa_mix_info info[MAX_MIX_CHANNELS];
unsigned n;
size_t l;
int r = -1;
assert(s && s->ref >= 1 && target && target->length && target->memblock && target->memblock->data);
assert(s);
assert(s->ref >= 1);
assert(target);
assert(target->memblock);
assert(target->length);
assert(target->memblock->data);
pa_sink_ref(s);
@ -268,27 +304,27 @@ int pa_sink_render_into(pa_sink*s, pa_memchunk *target) {
goto finish;
if (n == 1) {
uint32_t volume = PA_VOLUME_NORM;
pa_cvolume volume;
l = target->length;
if (l > info[0].chunk.length)
l = info[0].chunk.length;
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, l);
target->length = l;
memcpy((uint8_t*) target->memblock->data + target->index,
(uint8_t*) info[0].chunk.memblock->data + info[0].chunk.index,
target->length);
if (s->volume != PA_VOLUME_NORM || info[0].volume != PA_VOLUME_NORM)
volume = pa_volume_multiply(s->volume, info[0].volume);
if (volume != PA_VOLUME_NORM)
pa_volume_memchunk(target, &s->sample_spec, volume);
pa_sw_cvolume_multiply(&volume, &s->sw_volume, &info[0].volume);
if (!pa_cvolume_is_norm(&volume))
pa_volume_memchunk(target, &s->sample_spec, &volume);
} else
target->length = l = pa_mix(info, n, (uint8_t*) target->memblock->data+target->index, target->length, &s->sample_spec, s->volume);
target->length = pa_mix(info, n,
(uint8_t*) target->memblock->data + target->index,
target->length,
&s->sample_spec,
&s->sw_volume);
assert(l);
inputs_drop(s, info, n, l);
assert(s->monitor_source);
inputs_drop(s, info, n, target->length);
pa_source_post(s->monitor_source, target);
r = 0;
@ -302,7 +338,13 @@ finish:
void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
pa_memchunk chunk;
size_t l, d;
assert(s && s->ref >= 1 && target && target->memblock && target->length && target->memblock->data);
assert(s);
assert(s->ref >= 1);
assert(target);
assert(target->memblock);
assert(target->length);
assert(target->memblock->data);
pa_sink_ref(s);
@ -331,7 +373,10 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) {
}
void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
assert(s && s->ref >= 1 && length && result);
assert(s);
assert(s->ref >= 1);
assert(length);
assert(result);
/*** This needs optimization ***/
@ -342,7 +387,8 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) {
}
pa_usec_t pa_sink_get_latency(pa_sink *s) {
assert(s && s->ref >= 1);
assert(s);
assert(s->ref >= 1);
if (!s->get_latency)
return 0;
@ -351,7 +397,8 @@ pa_usec_t pa_sink_get_latency(pa_sink *s) {
}
void pa_sink_set_owner(pa_sink *s, pa_module *m) {
assert(s && s->ref >= 1);
assert(s);
assert(s->ref >= 1);
s->owner = m;
@ -359,11 +406,40 @@ void pa_sink_set_owner(pa_sink *s, pa_module *m) {
pa_source_set_owner(s->monitor_source, m);
}
void pa_sink_set_volume(pa_sink *s, pa_volume_t volume) {
assert(s && s->ref >= 1);
void pa_sink_set_volume(pa_sink *s, pa_mixer_t m, const pa_cvolume *volume) {
pa_cvolume *v;
if (s->volume != volume) {
s->volume = volume;
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
}
assert(s);
assert(s->ref >= 1);
assert(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->set_hw_volume(s) < 0)
s->sw_volume = *volume;
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
}
const pa_cvolume *pa_sink_get_volume(pa_sink *s, pa_mixer_t m) {
assert(s);
assert(s->ref >= 1);
if (m == PA_MIXER_HARDWARE && s->set_hw_volume) {
if (s->get_hw_volume)
s->get_hw_volume(s);
return &s->hw_volume;
} else
return &s->sw_volume;
}

View file

@ -30,39 +30,55 @@ typedef struct pa_sink pa_sink;
#include "sample.h"
#include "idxset.h"
#include "source.h"
#include "typeid.h"
#include "channelmap.h"
#include "module.h"
#include "volume.h"
#define PA_MAX_INPUTS_PER_SINK 6
typedef enum pa_sink_state {
PA_SINK_RUNNING,
PA_SINK_DISCONNECTED
} pa_sink_state;
} pa_sink_state_t;
typedef enum pa_mixer {
PA_MIXER_SOFTWARE,
PA_MIXER_HARDWARE
} pa_mixer_t;
struct pa_sink {
int ref;
pa_sink_state state;
uint32_t index;
pa_typeid_t typeid;
char *name, *description;
pa_module *owner;
pa_core *core;
pa_sink_state_t state;
char *name, *description, *driver;
pa_module *owner;
pa_sample_spec sample_spec;
pa_channel_map channel_map;
pa_idxset *inputs;
pa_source *monitor_source;
pa_volume_t volume;
pa_cvolume hw_volume, sw_volume;
void (*notify)(pa_sink*sink);
pa_usec_t (*get_latency)(pa_sink *s);
int (*set_hw_volume)(pa_sink *s);
int (*get_hw_volume)(pa_sink *s);
void *userdata;
};
pa_sink* pa_sink_new(pa_core *core, pa_typeid_t typeid, const char *name, int fail, const pa_sample_spec *spec);
pa_sink* pa_sink_new(
pa_core *core,
const char *driver,
const char *name,
int namereg_fail,
const pa_sample_spec *spec,
const pa_channel_map *map);
void pa_sink_disconnect(pa_sink* s);
void pa_sink_unref(pa_sink*s);
pa_sink* pa_sink_ref(pa_sink *s);
@ -78,6 +94,7 @@ void pa_sink_notify(pa_sink*s);
void pa_sink_set_owner(pa_sink *sink, pa_module *m);
void pa_sink_set_volume(pa_sink *sink, pa_volume_t volume);
void pa_sink_set_volume(pa_sink *sink, pa_mixer_t m, const pa_cvolume *volume);
const pa_cvolume *pa_sink_get_volume(pa_sink *sink, pa_mixer_t m);
#endif

View file

@ -173,7 +173,7 @@ static void connect_fixed_cb(pa_mainloop_api *m, pa_defer_event *e, void *userda
do_call(c);
}
static void connect_io_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) {
static void connect_io_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) {
pa_socket_client *c = userdata;
assert(m && c && c->io_event == e && fd >= 0);
do_call(c);
@ -344,7 +344,7 @@ pa_socket_client* pa_socket_client_new_ipv6(pa_mainloop_api *m, uint8_t address[
#ifdef HAVE_LIBASYNCNS
static void asyncns_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) {
static void asyncns_cb(pa_mainloop_api*m, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) {
pa_socket_client *c = userdata;
struct addrinfo *res = NULL;
int ret;

View file

@ -78,7 +78,7 @@ struct pa_socket_server {
enum { SOCKET_SERVER_GENERIC, SOCKET_SERVER_IPV4, SOCKET_SERVER_UNIX, SOCKET_SERVER_IPV6 } type;
};
static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags f, void *userdata) {
static void callback(pa_mainloop_api *mainloop, pa_io_event *e, int fd, PA_GCC_UNUSED pa_io_event_flags_t f, void *userdata) {
pa_socket_server *s = userdata;
pa_iochannel *io;
int nfd;

View file

@ -36,7 +36,6 @@
#include "log.h"
#define BUF_SIZE (1024*10)
#define PA_TYPEID_SOUND_FILE PA_TYPEID_MAKE('S', 'N', 'D', 'F')
struct userdata {
SNDFILE *sndfile;
@ -116,15 +115,12 @@ static void sink_input_drop(pa_sink_input *i, const pa_memchunk*chunk, size_t le
}
}
int pa_play_file(pa_sink *sink, const char *fname, pa_volume_t volume) {
int pa_play_file(pa_sink *sink, const char *fname, const pa_cvolume *volume) {
struct userdata *u = NULL;
SF_INFO sfinfo;
pa_sample_spec ss;
assert(sink && fname);
if (volume <= 0)
goto fail;
u = pa_xmalloc(sizeof(struct userdata));
u->sink_input = NULL;
u->memchunk.memblock = NULL;
@ -161,10 +157,11 @@ int pa_play_file(pa_sink *sink, const char *fname, pa_volume_t volume) {
goto fail;
}
if (!(u->sink_input = pa_sink_input_new(sink, PA_TYPEID_SOUND_FILE, fname, &ss, 0, -1)))
if (!(u->sink_input = pa_sink_input_new(sink, __FILE__, fname, &ss, NULL, 0, -1)))
goto fail;
u->sink_input->volume = volume;
if (volume)
u->sink_input->volume = *volume;
u->sink_input->peek = sink_input_peek;
u->sink_input->drop = sink_input_drop;
u->sink_input->kill = sink_input_kill;

View file

@ -24,6 +24,6 @@
#include "sink.h"
int pa_play_file(pa_sink *sink, const char *fname, pa_volume_t volume);
int pa_play_file(pa_sink *sink, const char *fname, const pa_cvolume *volume);
#endif

View file

@ -33,13 +33,24 @@
#include "subscribe.h"
#include "log.h"
pa_source_output* pa_source_output_new(pa_source *s, pa_typeid_t typeid, const char *name, const pa_sample_spec *spec, int resample_method) {
pa_source_output* pa_source_output_new(
pa_source *s,
const char *driver,
const char *name,
const pa_sample_spec *spec,
const pa_channel_map *map,
int resample_method) {
pa_source_output *o;
pa_resampler *resampler = NULL;
int r;
char st[256];
assert(s && spec);
pa_channel_map tmap;
assert(s);
assert(spec);
assert(s->state == PA_SOURCE_RUNNING);
if (pa_idxset_size(s->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) {
pa_log(__FILE__": Failed to create source output: too many outputs per source.\n");
return NULL;
@ -48,25 +59,31 @@ pa_source_output* pa_source_output_new(pa_source *s, pa_typeid_t typeid, const c
if (resample_method == PA_RESAMPLER_INVALID)
resample_method = s->core->resample_method;
if (!pa_sample_spec_equal(&s->sample_spec, spec))
if (!(resampler = pa_resampler_new(&s->sample_spec, spec, s->core->memblock_stat, resample_method)))
if (!map) {
pa_channel_map_init_auto(&tmap, spec->channels);
map = &tmap;
}
if (!pa_sample_spec_equal(&s->sample_spec, spec) || !pa_channel_map_equal(&s->channel_map, map))
if (!(resampler = pa_resampler_new(&s->sample_spec, &s->channel_map, spec, map, s->core->memblock_stat, resample_method)))
return NULL;
o = pa_xmalloc(sizeof(pa_source_output));
o->ref = 1;
o->state = PA_SOURCE_OUTPUT_RUNNING;
o->name = pa_xstrdup(name);
o->typeid = typeid;
o->client = NULL;
o->driver = pa_xstrdup(driver);
o->owner = NULL;
o->source = s;
o->client = NULL;
o->sample_spec = *spec;
o->channel_map = *map;
o->push = NULL;
o->kill = NULL;
o->userdata = NULL;
o->get_latency = NULL;
o->userdata = NULL;
o->resampler = resampler;
@ -85,7 +102,10 @@ pa_source_output* pa_source_output_new(pa_source *s, pa_typeid_t typeid, const c
}
void pa_source_output_disconnect(pa_source_output*o) {
assert(o && o->state != PA_SOURCE_OUTPUT_DISCONNECTED && o->source && o->source->core);
assert(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);
@ -95,7 +115,7 @@ void pa_source_output_disconnect(pa_source_output*o) {
o->push = NULL;
o->kill = NULL;
o->get_latency = NULL;
o->state = PA_SOURCE_OUTPUT_DISCONNECTED;
}
@ -112,26 +132,31 @@ static void source_output_free(pa_source_output* o) {
pa_resampler_free(o->resampler);
pa_xfree(o->name);
pa_xfree(o->driver);
pa_xfree(o);
}
void pa_source_output_unref(pa_source_output* o) {
assert(o && o->ref >= 1);
assert(o);
assert(o->ref >= 1);
if (!(--o->ref))
source_output_free(o);
}
pa_source_output* pa_source_output_ref(pa_source_output *o) {
assert(o && o->ref >= 1);
assert(o);
assert(o->ref >= 1);
o->ref++;
return o;
}
void pa_source_output_kill(pa_source_output*o) {
assert(o && o->ref >= 1);
assert(o);
assert(o->ref >= 1);
if (o->kill)
o->kill(o);
@ -139,7 +164,11 @@ void pa_source_output_kill(pa_source_output*o) {
void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
pa_memchunk rchunk;
assert(o && chunk && chunk->length && o->push);
assert(o);
assert(chunk);
assert(chunk->length);
assert(o->push);
if (o->state == PA_SOURCE_OUTPUT_CORKED)
return;
@ -159,7 +188,9 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) {
}
void pa_source_output_set_name(pa_source_output *o, const char *name) {
assert(o && o->ref >= 1);
assert(o);
assert(o->ref >= 1);
pa_xfree(o->name);
o->name = pa_xstrdup(name);
@ -167,7 +198,8 @@ void pa_source_output_set_name(pa_source_output *o, const char *name) {
}
pa_usec_t pa_source_output_get_latency(pa_source_output *o) {
assert(o && o->ref >= 1);
assert(o);
assert(o->ref >= 1);
if (o->get_latency)
return o->get_latency(o);
@ -176,7 +208,8 @@ pa_usec_t pa_source_output_get_latency(pa_source_output *o) {
}
void pa_source_output_cork(pa_source_output *o, int b) {
assert(o && o->ref >= 1);
assert(o);
assert(o->ref >= 1);
if (o->state == PA_SOURCE_OUTPUT_DISCONNECTED)
return;
@ -184,9 +217,10 @@ void pa_source_output_cork(pa_source_output *o, int b) {
o->state = b ? PA_SOURCE_OUTPUT_CORKED : PA_SOURCE_OUTPUT_RUNNING;
}
pa_resample_method pa_source_output_get_resample_method(pa_source_output *o) {
assert(o && o->ref >= 1);
pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o) {
assert(o);
assert(o->ref >= 1);
if (!o->resampler)
return PA_RESAMPLER_INVALID;

View file

@ -37,20 +37,21 @@ typedef enum {
PA_SOURCE_OUTPUT_RUNNING,
PA_SOURCE_OUTPUT_CORKED,
PA_SOURCE_OUTPUT_DISCONNECTED
} pa_source_output_state;
} pa_source_output_state_t;
struct pa_source_output {
int ref;
pa_source_output_state state;
uint32_t index;
pa_typeid_t typeid;
char *name;
pa_source_output_state_t state;
char *name, *driver;
pa_module *owner;
pa_client *client;
pa_source *source;
pa_client *client;
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);
@ -61,7 +62,14 @@ struct pa_source_output {
void *userdata;
};
pa_source_output* pa_source_output_new(pa_source *s, pa_typeid_t typeid, const char *name, const pa_sample_spec *spec, int resample_method);
pa_source_output* pa_source_output_new(
pa_source *s,
const char *driver,
const char *name,
const pa_sample_spec *spec,
const pa_channel_map *map,
int resample_method);
void pa_source_output_unref(pa_source_output* o);
pa_source_output* pa_source_output_ref(pa_source_output *o);
@ -79,6 +87,6 @@ pa_usec_t pa_source_output_get_latency(pa_source_output *i);
void pa_source_output_cork(pa_source_output *i, int b);
pa_resample_method pa_source_output_get_resample_method(pa_source_output *o);
pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o);
#endif

Some files were not shown because too many files have changed in this diff Show more