mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
* fix include file names in installed header files
* add browsing API * add new tool pabrowse * add typeid subsystem * bump API version * split off random.c * add an identification cookie git-svn-id: file:///home/lennart/svn/public/pulseaudio/trunk@320 fefdeb5f-60dc-0310-8127-8f9354f1896f
This commit is contained in:
parent
9a01cf44f0
commit
e02be6c15b
58 changed files with 971 additions and 169 deletions
|
|
@ -20,7 +20,7 @@
|
|||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||||
|
||||
AC_PREREQ(2.57)
|
||||
AC_INIT([polypaudio],[0.7.1],[mzcbylcnhqvb (at) 0pointer (dot) de])
|
||||
AC_INIT([polypaudio],[0.8],[mzcbylcnhqvb (at) 0pointer (dot) de])
|
||||
AC_CONFIG_SRCDIR([polyp/main.c])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AM_INIT_AUTOMAKE([foreign -Wall])
|
||||
|
|
@ -28,7 +28,7 @@ AM_INIT_AUTOMAKE([foreign -Wall])
|
|||
AC_SUBST(PA_MAJORMINOR, "$PACKAGE_VERSION")
|
||||
AC_SUBST(PACKAGE_URL, [http://0pointer.de/lennart/projects/polypaudio/])
|
||||
|
||||
AC_SUBST(PA_API_VERSION, 7)
|
||||
AC_SUBST(PA_API_VERSION, 8)
|
||||
|
||||
if type -p stow > /dev/null && test -d /usr/local/stow ; then
|
||||
AC_MSG_NOTICE([*** Found /usr/local/stow: default install prefix set to /usr/local/stow/${PACKAGE_NAME}-${PACKAGE_VERSION} ***])
|
||||
|
|
|
|||
26
doc/todo
26
doc/todo
|
|
@ -1,23 +1,31 @@
|
|||
*** $Id$ ***
|
||||
|
||||
*** later ****
|
||||
- event more commenting
|
||||
- polish for starting polypaudio as root/system-wide instance
|
||||
Architectural changes:
|
||||
- per-channel volume
|
||||
- channel mapping ("left", "right", "rear", "subwoofer")
|
||||
- add API for synchronizing multiple sinks/sources to a common clock
|
||||
- absolutely indexed write()s from client
|
||||
- remove "polyplib-" prefix
|
||||
|
||||
Fixes:
|
||||
- improve module-oss-mmap latency measurement
|
||||
- module-tunnel: improve latency calculation
|
||||
- make alsa modules use mmap
|
||||
- event more commenting
|
||||
|
||||
Features:
|
||||
- add radio module
|
||||
- pass meta info for hearing impaired
|
||||
- add sync API
|
||||
- X11: support for the X11 synchronization extension
|
||||
- xmlrpc/http
|
||||
- dbus
|
||||
- rendezvous
|
||||
- make alsa modules use mmap
|
||||
- polish for starting polypaudio as root/system-wide instance
|
||||
- export connection fd
|
||||
|
||||
***********
|
||||
Long term:
|
||||
- pass meta info for hearing impaired
|
||||
- X11: support for the X11 synchronization extension
|
||||
|
||||
backends for:
|
||||
Backends for:
|
||||
- portaudio (semi-done)
|
||||
- alsa-lib
|
||||
- sdl
|
||||
|
|
|
|||
|
|
@ -220,7 +220,9 @@ polypaudio_SOURCES = idxset.c idxset.h \
|
|||
props.h props.c \
|
||||
mcalign.c mcalign.h \
|
||||
g711.c g711.h \
|
||||
pid.c pid.h
|
||||
pid.c pid.h \
|
||||
random.c random.h \
|
||||
typeid.c typeid.h
|
||||
|
||||
polypaudio_CFLAGS = $(AM_CFLAGS) $(LIBSAMPLERATE_CFLAGS) $(LIBSNDFILE_CFLAGS)
|
||||
polypaudio_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL)
|
||||
|
|
@ -455,7 +457,9 @@ libpolyp_@PA_MAJORMINOR@_la_SOURCES = polyplib.h \
|
|||
conf-parser.c conf-parser.h \
|
||||
strlist.c strlist.h \
|
||||
strbuf.c strbuf.h \
|
||||
mcalign.c mcalign.h
|
||||
mcalign.c mcalign.h \
|
||||
typeid.c typeid.h \
|
||||
random.c random.h
|
||||
|
||||
libpolyp_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS)
|
||||
libpolyp_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0
|
||||
|
|
@ -560,7 +564,7 @@ module_x11_publish_la_LIBADD = $(AM_LIBADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EX
|
|||
bin_PROGRAMS+= \
|
||||
pax11publish
|
||||
|
||||
pax11publish_SOURCES = pax11publish.c util.c xmalloc.c log.c authkey.c client-conf.c conf-parser.c x11prop.c
|
||||
pax11publish_SOURCES = pax11publish.c util.c util.h xmalloc.c xmalloc.h log.c log.h authkey.c authkey.h client-conf.c client-conf.h conf-parser.c conf-parser.h x11prop.c x11prop.h random.c random.h
|
||||
pax11publish_CFLAGS = $(AM_CFLAGS) $(X_CFLAGS)
|
||||
pax11publish_LDADD = $(AM_LDADD) $(X_PRE_LIBS) -lX11 $(X_LIBS) $(X_EXTRA_LIBS)
|
||||
|
||||
|
|
@ -613,6 +617,21 @@ module_zeroconf_publish_la_LDFLAGS = -module -avoid-version
|
|||
module_zeroconf_publish_la_LIBADD = $(AM_LIBADD) $(HOWL_LIBS) libhowl-wrap.la
|
||||
module_zeroconf_publish_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS)
|
||||
|
||||
lib_LTLIBRARIES+= \
|
||||
libpolyp-browse-@PA_MAJORMINOR@.la
|
||||
|
||||
libpolyp_browse_@PA_MAJORMINOR@_la_SOURCES = polyplib-browser.c polyplib-browser.h
|
||||
libpolyp_browse_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(HOWL_CFLAGS)
|
||||
libpolyp_browse_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la $(HOWL_LIBS)
|
||||
libpolyp_browse_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0
|
||||
|
||||
bin_PROGRAMS += \
|
||||
pabrowse
|
||||
|
||||
pabrowse_SOURCES = pabrowse.c
|
||||
pabrowse_LDADD = $(AM_LDADD) libpolyp-@PA_MAJORMINOR@.la libpolyp-error-@PA_MAJORMINOR@.la libpolyp-mainloop-@PA_MAJORMINOR@.la libpolyp-browse-@PA_MAJORMINOR@.la
|
||||
pabrowse_CFLAGS = $(AM_CFLAGS)
|
||||
|
||||
endif
|
||||
|
||||
### GLIB 2.0 support
|
||||
|
|
|
|||
|
|
@ -38,50 +38,24 @@
|
|||
#include "authkey.h"
|
||||
#include "util.h"
|
||||
#include "log.h"
|
||||
|
||||
#define RANDOM_DEVICE "/dev/urandom"
|
||||
#include "random.h"
|
||||
|
||||
/* Generate a new authorization key, store it in file fd and return it in *data */
|
||||
static int generate(int fd, void *data, size_t length) {
|
||||
int random_fd, ret = -1;
|
||||
static int generate(int fd, void *ret_data, size_t length) {
|
||||
ssize_t r;
|
||||
assert(fd >= 0 && data && length);
|
||||
assert(fd >= 0 && ret_data && length);
|
||||
|
||||
if ((random_fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) {
|
||||
|
||||
if ((r = pa_loop_read(random_fd, data, length)) < 0 || (size_t) r != length) {
|
||||
pa_log(__FILE__": failed to read entropy from '%s'\n", RANDOM_DEVICE);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
} else {
|
||||
uint8_t *p;
|
||||
size_t l;
|
||||
pa_log(__FILE__": WARNING: Failed to open entropy device '"RANDOM_DEVICE"': %s"
|
||||
", falling back to unsecure pseudo RNG.\n", strerror(errno));
|
||||
|
||||
srandom(time(NULL));
|
||||
|
||||
for (p = data, l = length; l > 0; p++, l--)
|
||||
*p = (uint8_t) random();
|
||||
}
|
||||
pa_random(ret_data, length);
|
||||
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
ftruncate(fd, 0);
|
||||
|
||||
if ((r = pa_loop_write(fd, data, length)) < 0 || (size_t) r != length) {
|
||||
if ((r = pa_loop_write(fd, ret_data, length)) < 0 || (size_t) r != length) {
|
||||
pa_log(__FILE__": failed to write cookie file: %s\n", strerror(errno));
|
||||
goto finish;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
finish:
|
||||
|
||||
if (random_fd >= 0)
|
||||
close(random_fd);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Load an euthorization cookie from file fn and store it in data. If
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ char *pa_client_list_to_string(struct pa_core *c) {
|
|||
struct pa_strbuf *s;
|
||||
struct pa_client *client;
|
||||
uint32_t index = PA_IDXSET_INVALID;
|
||||
char tid[5];
|
||||
assert(c);
|
||||
|
||||
s = pa_strbuf_new();
|
||||
|
|
@ -67,7 +68,7 @@ char *pa_client_list_to_string(struct pa_core *c) {
|
|||
pa_strbuf_printf(s, "%u client(s) logged in.\n", pa_idxset_ncontents(c->clients));
|
||||
|
||||
for (client = pa_idxset_first(c->clients, &index); client; client = pa_idxset_next(c->clients, &index)) {
|
||||
pa_strbuf_printf(s, " index: %u\n\tname: <%s>\n\tprotocol_name: <%s>\n", client->index, client->name, client->protocol_name);
|
||||
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)));
|
||||
|
||||
if (client->owner)
|
||||
pa_strbuf_printf(s, "\towner module: <%u>\n", client->owner->index);
|
||||
|
|
@ -80,6 +81,7 @@ char *pa_sink_list_to_string(struct pa_core *c) {
|
|||
struct pa_strbuf *s;
|
||||
struct pa_sink *sink;
|
||||
uint32_t index = PA_IDXSET_INVALID;
|
||||
char tid[5];
|
||||
assert(c);
|
||||
|
||||
s = pa_strbuf_new();
|
||||
|
|
@ -93,9 +95,10 @@ char *pa_sink_list_to_string(struct pa_core *c) {
|
|||
assert(sink->monitor_source);
|
||||
pa_strbuf_printf(
|
||||
s,
|
||||
" %c index: %u\n\tname: <%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\ttype: <%s>\n\tvolume: <0x%04x> (%0.2fdB)\n\tlatency: <%0.0f usec>\n\tmonitor_source: <%u>\n\tsample_spec: <%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),
|
||||
(float) pa_sink_get_latency(sink),
|
||||
|
|
@ -115,6 +118,7 @@ char *pa_source_list_to_string(struct pa_core *c) {
|
|||
struct pa_strbuf *s;
|
||||
struct pa_source *source;
|
||||
uint32_t index = PA_IDXSET_INVALID;
|
||||
char tid[5];
|
||||
assert(c);
|
||||
|
||||
s = pa_strbuf_new();
|
||||
|
|
@ -125,10 +129,11 @@ char *pa_source_list_to_string(struct pa_core *c) {
|
|||
for (source = pa_idxset_first(c->sources, &index); source; source = pa_idxset_next(c->sources, &index)) {
|
||||
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\tlatency: <%0.0f usec>\n\tsample_spec: <%s>\n",
|
||||
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)),
|
||||
(float) pa_source_get_latency(source),
|
||||
ss);
|
||||
|
||||
|
|
@ -148,6 +153,7 @@ char *pa_source_output_list_to_string(struct pa_core *c) {
|
|||
struct pa_strbuf *s;
|
||||
struct pa_source_output *o;
|
||||
uint32_t index = PA_IDXSET_INVALID;
|
||||
char tid[5];
|
||||
static const char* const state_table[] = {
|
||||
"RUNNING",
|
||||
"CORKED",
|
||||
|
|
@ -170,9 +176,10 @@ char *pa_source_output_list_to_string(struct pa_core *c) {
|
|||
rm = "invalid";
|
||||
|
||||
pa_strbuf_printf(
|
||||
s, " index: %u\n\tname: '%s'\n\tstate: %s\n\tsource: <%u> '%s'\n\tsample_spec: <%s>\n\tresample method: %s\n",
|
||||
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",
|
||||
o->index,
|
||||
o->name,
|
||||
pa_typeid_to_string(o->typeid, tid, sizeof(tid)),
|
||||
state_table[o->state],
|
||||
o->source->index, o->source->name,
|
||||
ss,
|
||||
|
|
@ -190,6 +197,7 @@ char *pa_sink_input_list_to_string(struct pa_core *c) {
|
|||
struct pa_strbuf *s;
|
||||
struct pa_sink_input *i;
|
||||
uint32_t index = PA_IDXSET_INVALID;
|
||||
char tid[5];
|
||||
static const char* const state_table[] = {
|
||||
"RUNNING",
|
||||
"CORKED",
|
||||
|
|
@ -212,9 +220,10 @@ char *pa_sink_input_list_to_string(struct pa_core *c) {
|
|||
pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec);
|
||||
assert(i->sink);
|
||||
pa_strbuf_printf(
|
||||
s, " index: %u\n\tname: <%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\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",
|
||||
i->index,
|
||||
i->name,
|
||||
pa_typeid_to_string(i->typeid, tid, sizeof(tid)),
|
||||
state_table[i->state],
|
||||
i->sink->index, i->sink->name,
|
||||
(unsigned) i->volume,
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#include "log.h"
|
||||
|
||||
#define PROMPT ">>> "
|
||||
#define PA_TYPEID_CLI PA_TYPEID_MAKE('C', 'L', 'I', '_')
|
||||
|
||||
struct pa_cli {
|
||||
struct pa_core *core;
|
||||
|
|
@ -75,7 +76,7 @@ struct pa_cli* pa_cli_new(struct pa_core *core, struct pa_iochannel *io, struct
|
|||
c->eof_callback = NULL;
|
||||
|
||||
pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname));
|
||||
c->client = pa_client_new(core, "CLI", cname);
|
||||
c->client = pa_client_new(core, PA_TYPEID_CLI, cname);
|
||||
assert(c->client);
|
||||
c->client->kill = client_kill;
|
||||
c->client->userdata = c;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
#include "subscribe.h"
|
||||
#include "log.h"
|
||||
|
||||
struct pa_client *pa_client_new(struct pa_core *core, const char *protocol_name, char *name) {
|
||||
struct pa_client *pa_client_new(struct pa_core *core, pa_typeid_t typeid, const char *name) {
|
||||
struct pa_client *c;
|
||||
int r;
|
||||
assert(core);
|
||||
|
|
@ -42,7 +42,7 @@ struct pa_client *pa_client_new(struct pa_core *core, const char *protocol_name,
|
|||
c->name = pa_xstrdup(name);
|
||||
c->owner = NULL;
|
||||
c->core = core;
|
||||
c->protocol_name = pa_xstrdup(protocol_name);
|
||||
c->typeid = typeid;
|
||||
|
||||
c->kill = NULL;
|
||||
c->userdata = NULL;
|
||||
|
|
@ -68,7 +68,6 @@ void pa_client_free(struct 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->protocol_name);
|
||||
pa_xfree(c);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#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
|
||||
|
|
@ -31,18 +32,17 @@
|
|||
|
||||
struct pa_client {
|
||||
uint32_t index;
|
||||
pa_typeid_t typeid;
|
||||
|
||||
struct pa_module *owner;
|
||||
char *name;
|
||||
struct pa_core *core;
|
||||
char *protocol_name;
|
||||
|
||||
void (*kill)(struct pa_client *c);
|
||||
void *userdata;
|
||||
};
|
||||
|
||||
/* Protocol name should be something like "ESOUND", "NATIVE", ... */
|
||||
struct pa_client *pa_client_new(struct pa_core *c, const char *protocol_name, char *name);
|
||||
struct pa_client *pa_client_new(struct pa_core *c, pa_typeid_t typeid, const char *name);
|
||||
|
||||
/* This function should be called only by the code that created the client */
|
||||
void pa_client_free(struct pa_client *c);
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include "xmalloc.h"
|
||||
#include "subscribe.h"
|
||||
#include "props.h"
|
||||
#include "random.h"
|
||||
|
||||
struct pa_core* pa_core_new(struct pa_mainloop_api *m) {
|
||||
struct pa_core* c;
|
||||
|
|
@ -85,8 +86,9 @@ struct pa_core* pa_core_new(struct pa_mainloop_api *m) {
|
|||
|
||||
pa_property_init(c);
|
||||
|
||||
pa_check_signal_is_blocked(SIGPIPE);
|
||||
pa_random(&c->cookie, sizeof(c->cookie));
|
||||
|
||||
pa_check_signal_is_blocked(SIGPIPE);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,10 @@
|
|||
* variables for the daemon. */
|
||||
|
||||
struct pa_core {
|
||||
/* A random value which may be used to identify this instance of
|
||||
* polypaudio. Not cryptographically secure in any way. */
|
||||
uint32_t cookie;
|
||||
|
||||
struct pa_mainloop_api *mainloop;
|
||||
|
||||
/* idxset of all kinds of entities */
|
||||
|
|
|
|||
|
|
@ -31,32 +31,44 @@
|
|||
#define INT16_SWAP(x) ((int16_t)(((int16_t) x >> 8) | ((int16_t) x << 8)))
|
||||
#define UINT16_SWAP(x) ((uint16_t)(((uint16_t) x >> 8) | ((uint16_t) x << 8)))
|
||||
#define INT32_SWAP(x) ((int32_t)(((int32_t) x >> 24) | ((int32_t) x << 24) | (((int32_t) x & 0xFF00) << 16) | (((int32_t) x) >> 16) & 0xFF00))
|
||||
#define UINT32_SWAP(x) ((uint32_t)(((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 16) | (((uint32_t) x) >> 16) & 0xFF00))
|
||||
#define UINT32_SWAP(x) ((uint32_t)(((uint32_t) x >> 24) | ((uint32_t) x << 24) | (((uint32_t) x & 0xFF00) << 16) | ((((uint32_t) x) >> 16) & 0xFF00)))
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
#define INT16_FROM_LE(x) INT16_SWAP(x)
|
||||
#define INT16_FROM_BE(x) ((int16_t)(x))
|
||||
|
||||
#define INT16_TO_LE(x) INT16_SWAP(x)
|
||||
#define INT16_TO_BE(x) ((int16_t)(x))
|
||||
|
||||
#define UINT16_FROM_LE(x) UINT16_SWAP(x)
|
||||
#define UINT16_FROM_BE(x) ((uint16_t)(x))
|
||||
|
||||
#define INT32_FROM_LE(x) INT32_SWAP(x)
|
||||
#define INT32_FROM_BE(x) ((int32_t)(x))
|
||||
|
||||
#define UINT32_FROM_LE(x) UINT32_SWAP(x)
|
||||
#define UINT32_FROM_BE(x) ((uint32_t)(x))
|
||||
|
||||
#define UINT32_TO_LE(x) UINT32_SWAP(x)
|
||||
#define UINT32_TO_BE(x) ((uint32_t)(x))
|
||||
#else
|
||||
#define INT16_FROM_LE(x) ((int16_t)(x))
|
||||
#define INT16_FROM_BE(x) INT16_SWAP(x)
|
||||
|
||||
#define INT16_TO_LE(x) ((int16_t)(x))
|
||||
#define INT16_TO_BE(x) INT16_SWAP(x)
|
||||
|
||||
#define UINT16_FROM_LE(x) ((uint16_t)(x))
|
||||
#define UINT16_FROM_BE(x) UINT16_SWAP(x)
|
||||
|
||||
#define INT32_FROM_LE(x) ((int32_t)(x))
|
||||
#define INT32_FROM_BE(x) INT32_SWAP(x)
|
||||
|
||||
#define UINT32_FROM_LE(x) ((uint32_t)(x))
|
||||
#define UINT32_FROM_BE(x) UINT32_SWAP(x)
|
||||
|
||||
#define UINT32_TO_LE(x) ((uint32_t)(x))
|
||||
#define UINT32_TO_BE(x) UINT32_SWAP(x)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "cdecl.h"
|
||||
#include <polyp/cdecl.h>
|
||||
|
||||
/** \file
|
||||
*
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ 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;
|
||||
struct pa_sink *sink;
|
||||
|
|
@ -212,7 +214,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss);
|
||||
u->sink = pa_sink_new(c, PA_TYPEID_ALSA, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss);
|
||||
assert(u->sink);
|
||||
|
||||
u->sink->get_latency = sink_get_latency_cb;
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ 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;
|
||||
struct pa_source *source;
|
||||
|
|
@ -203,7 +205,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
u->source = pa_source_new(c, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss);
|
||||
u->source = pa_source_new(c, PA_TYPEID_ALSA, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss);
|
||||
assert(u->source);
|
||||
|
||||
u->source->userdata = u;
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ 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)
|
||||
|
|
@ -214,7 +216,7 @@ static struct output *output_new(struct userdata *u, struct pa_sink *sink, int r
|
|||
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, t, &u->sink->sample_spec, 1, resample_method)))
|
||||
if (!(o->sink_input = pa_sink_input_new(sink, PA_TYPEID_COMBINE, t, &u->sink->sample_spec, 1, resample_method)))
|
||||
goto fail;
|
||||
|
||||
o->sink_input->get_latency = sink_input_get_latency_cb;
|
||||
|
|
@ -325,7 +327,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (!(u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &master_sink->sample_spec))) {
|
||||
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))) {
|
||||
pa_log(__FILE__": failed to create sink\n");
|
||||
goto fail;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ PA_MODULE_USAGE("sink_name=<name for the sink> server=<address> cookie=<filename
|
|||
|
||||
#define DEFAULT_SINK_NAME "esound_output"
|
||||
|
||||
#define PA_TYPEID_ESOUND_SINK PA_TYPEID_MAKE('E', 'S', 'D', 'S')
|
||||
|
||||
struct userdata {
|
||||
struct pa_core *core;
|
||||
|
||||
|
|
@ -352,7 +354,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
|
|||
u->state = STATE_AUTH;
|
||||
u->latency = 0;
|
||||
|
||||
if (!(u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) {
|
||||
if (!(u->sink = pa_sink_new(c, PA_TYPEID_ESOUND_SINK, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) {
|
||||
pa_log(__FILE__": failed to create sink.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ 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 {
|
||||
struct pa_core *core;
|
||||
struct pa_module *module;
|
||||
|
|
@ -106,7 +108,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
|
|||
u->module = m;
|
||||
m->userdata = u;
|
||||
|
||||
if (!(u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) {
|
||||
if (!(u->sink = pa_sink_new(c, PA_TYPEID_NULL, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) {
|
||||
pa_log(__FILE__": failed to create sink.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,8 @@ 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 {
|
||||
struct pa_sink *sink;
|
||||
struct pa_source *source;
|
||||
|
|
@ -302,7 +304,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
|
|||
}
|
||||
} else {
|
||||
|
||||
u->source = pa_source_new(c, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &u->sample_spec);
|
||||
u->source = pa_source_new(c, PA_TYPEID_OSS_MMAP, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &u->sample_spec);
|
||||
assert(u->source);
|
||||
u->source->userdata = u;
|
||||
pa_source_set_owner(u->source, m);
|
||||
|
|
@ -334,7 +336,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
|
|||
} else {
|
||||
pa_silence_memory(u->out_mmap, u->out_mmap_length, &u->sample_spec);
|
||||
|
||||
u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &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);
|
||||
assert(u->sink);
|
||||
u->sink->get_latency = sink_get_latency_cb;
|
||||
u->sink->userdata = u;
|
||||
|
|
|
|||
|
|
@ -52,6 +52,8 @@ 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 {
|
||||
struct pa_sink *sink;
|
||||
struct pa_source *source;
|
||||
|
|
@ -325,7 +327,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
|
|||
}
|
||||
|
||||
if (mode != O_WRONLY) {
|
||||
u->source = pa_source_new(c, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss);
|
||||
u->source = pa_source_new(c, PA_TYPEID_OSS, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss);
|
||||
assert(u->source);
|
||||
u->source->userdata = u;
|
||||
u->source->get_latency = source_get_latency_cb;
|
||||
|
|
@ -335,7 +337,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
|
|||
u->source = NULL;
|
||||
|
||||
if (mode != O_RDONLY) {
|
||||
u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss);
|
||||
u->sink = pa_sink_new(c, PA_TYPEID_OSS, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss);
|
||||
assert(u->sink);
|
||||
u->sink->get_latency = sink_get_latency_cb;
|
||||
u->sink->userdata = u;
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ 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 {
|
||||
struct pa_core *core;
|
||||
|
||||
|
|
@ -175,7 +177,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
|
|||
u->module = m;
|
||||
m->userdata = u;
|
||||
|
||||
if (!(u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) {
|
||||
if (!(u->sink = pa_sink_new(c, PA_TYPEID_PIPE, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) {
|
||||
pa_log(__FILE__": failed to create sink.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ 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 {
|
||||
struct pa_core *core;
|
||||
|
||||
|
|
@ -152,7 +154,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
|
|||
u->filename = pa_xstrdup(p);
|
||||
u->core = c;
|
||||
|
||||
if (!(u->source = pa_source_new(c, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss))) {
|
||||
if (!(u->source = pa_source_new(c, PA_TYPEID_PIPE, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss))) {
|
||||
pa_log(__FILE__": failed to create source.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ 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 {
|
||||
struct pa_core *core;
|
||||
struct pa_module *module;
|
||||
|
|
@ -140,7 +142,7 @@ int pa__init(struct pa_core *c, struct 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, t, &ss, 0, -1)))
|
||||
if (!(u->sink_input = pa_sink_input_new(sink, PA_TYPEID_SINE, t, &ss, 0, -1)))
|
||||
goto fail;
|
||||
|
||||
u->sink_input->peek = sink_input_peek;
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@ 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"
|
||||
|
||||
|
|
@ -624,7 +626,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
|
|||
pa_socket_client_set_callback(u->client, on_connection, u);
|
||||
|
||||
#ifdef TUNNEL_SINK
|
||||
if (!(u->sink = pa_sink_new(c, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) {
|
||||
if (!(u->sink = pa_sink_new(c, PA_TYPEID_TUNNEL, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME), 0, &ss))) {
|
||||
pa_log(__FILE__": failed to create sink.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -636,7 +638,7 @@ int pa__init(struct pa_core *c, struct pa_module*m) {
|
|||
|
||||
pa_sink_set_owner(u->sink, m);
|
||||
#else
|
||||
if (!(u->source = pa_source_new(c, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss))) {
|
||||
if (!(u->source = pa_source_new(c, PA_TYPEID_TUNNEL, pa_modargs_get_value(ma, "source_name", DEFAULT_SOURCE_NAME), 0, &ss))) {
|
||||
pa_log(__FILE__": failed to create source.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include "log.h"
|
||||
#include "subscribe.h"
|
||||
#include "dynarray.h"
|
||||
#include "endianmacros.h"
|
||||
|
||||
PA_MODULE_AUTHOR("Lennart Poettering")
|
||||
PA_MODULE_DESCRIPTION("mDNS/DNS-SD Service Publisher")
|
||||
|
|
@ -79,21 +80,36 @@ static sw_result publish_reply(sw_discovery discovery, sw_discovery_publish_stat
|
|||
return SW_OKAY;
|
||||
}
|
||||
|
||||
static void get_service_sample_spec(struct userdata *u, struct service *s, struct pa_sample_spec *ret_ss) {
|
||||
assert(u && s && s->loaded.valid && ret_ss);
|
||||
static void get_service_data(struct userdata *u, struct service *s, struct pa_sample_spec *ret_ss, char **ret_description, pa_typeid_t *ret_typeid) {
|
||||
assert(u && s && s->loaded.valid && ret_ss && ret_description && ret_typeid);
|
||||
|
||||
if (s->loaded.type == PA_NAMEREG_SINK) {
|
||||
struct pa_sink *sink = pa_idxset_get_by_index(u->core->sinks, s->loaded.index);
|
||||
assert(sink);
|
||||
*ret_ss = sink->sample_spec;
|
||||
*ret_description = sink->description;
|
||||
*ret_typeid = sink->typeid;
|
||||
} else if (s->loaded.type == PA_NAMEREG_SOURCE) {
|
||||
struct pa_source *source = pa_idxset_get_by_index(u->core->sources, s->loaded.index);
|
||||
assert(source);
|
||||
*ret_ss = source->sample_spec;
|
||||
*ret_description = source->description;
|
||||
*ret_typeid = source->typeid;
|
||||
} else
|
||||
assert(0);
|
||||
}
|
||||
|
||||
static void txt_record_server_data(struct pa_core *c, sw_text_record t) {
|
||||
char s[256];
|
||||
assert(c);
|
||||
|
||||
sw_text_record_add_key_and_string_value(t, "server-version", PACKAGE_NAME" "PACKAGE_VERSION);
|
||||
sw_text_record_add_key_and_string_value(t, "user-name", pa_get_user_name(s, sizeof(s)));
|
||||
sw_text_record_add_key_and_string_value(t, "fqdn", pa_get_fqdn(s, sizeof(s)));
|
||||
snprintf(s, sizeof(s), "0x%08x", c->cookie);
|
||||
sw_text_record_add_key_and_string_value(t, "cookie", s);
|
||||
}
|
||||
|
||||
static int publish_service(struct userdata *u, struct service *s) {
|
||||
assert(u && s);
|
||||
char t[256];
|
||||
|
|
@ -121,11 +137,14 @@ static int publish_service(struct userdata *u, struct service *s) {
|
|||
|
||||
sw_text_record_add_key_and_string_value(txt, "device", s->name);
|
||||
|
||||
txt_record_server_data(u->core, txt);
|
||||
|
||||
if (s->loaded.valid) {
|
||||
char z[64];
|
||||
char z[64], *description;
|
||||
pa_typeid_t typeid;
|
||||
struct pa_sample_spec ss;
|
||||
|
||||
get_service_sample_spec(u, s, &ss);
|
||||
get_service_data(u, s, &ss, &description, &typeid);
|
||||
|
||||
snprintf(z, sizeof(z), "%u", ss.rate);
|
||||
sw_text_record_add_key_and_string_value(txt, "rate", z);
|
||||
|
|
@ -133,6 +152,12 @@ static int publish_service(struct userdata *u, struct service *s) {
|
|||
sw_text_record_add_key_and_string_value(txt, "channels", z);
|
||||
sw_text_record_add_key_and_string_value(txt, "format", pa_sample_format_to_string(ss.format));
|
||||
|
||||
sw_text_record_add_key_and_string_value(txt, "description", description);
|
||||
|
||||
snprintf(z, sizeof(z), "0x%8x", typeid);
|
||||
sw_text_record_add_key_and_string_value(txt, "typeid", z);
|
||||
|
||||
|
||||
if (sw_discovery_publish(pa_howl_wrapper_get_discovery(u->howl_wrapper), 0, t,
|
||||
s->loaded.type == PA_NAMEREG_SINK ? SERVICE_NAME_SINK : SERVICE_NAME_SOURCE,
|
||||
NULL, NULL, PA_NATIVE_DEFAULT_PORT, sw_text_record_bytes(txt), sw_text_record_len(txt),
|
||||
|
|
|
|||
139
polyp/pabrowse.c
Normal file
139
polyp/pabrowse.c
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/* $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 <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <polyp/mainloop.h>
|
||||
#include <polyp/mainloop-signal.h>
|
||||
#include <polyp/polyplib-browser.h>
|
||||
#include <polyp/typeid.h>
|
||||
|
||||
static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) {
|
||||
fprintf(stderr, "Got signal, exiting\n");
|
||||
m->quit(m, 0);
|
||||
}
|
||||
|
||||
static void dump_server(const struct pa_browse_info *i) {
|
||||
char t[16];
|
||||
|
||||
if (i->cookie)
|
||||
snprintf(t, sizeof(t), "0x%08x", *i->cookie);
|
||||
|
||||
printf("server: %s\n"
|
||||
"server-version: %s\n"
|
||||
"user-name: %s\n"
|
||||
"fqdn: %s\n"
|
||||
"cookie: %s\n",
|
||||
i->server,
|
||||
i->server_version ? i->server_version : "n/a",
|
||||
i->user_name ? i->user_name : "n/a",
|
||||
i->fqdn ? i->fqdn : "n/a",
|
||||
i->cookie ? t : "n/a");
|
||||
}
|
||||
|
||||
static void dump_device(const struct pa_browse_info *i) {
|
||||
char t[16], ss[PA_SAMPLE_SPEC_SNPRINT_MAX];
|
||||
|
||||
if (i->sample_spec)
|
||||
pa_sample_spec_snprint(ss, sizeof(ss), i->sample_spec);
|
||||
|
||||
if (i->typeid)
|
||||
pa_typeid_to_string(*i->typeid, t, sizeof(t));
|
||||
|
||||
printf("device: %s\n"
|
||||
"description: %s\n"
|
||||
"type: %s\n"
|
||||
"sample spec: %s\n",
|
||||
i->device,
|
||||
i->description ? i->description : "n/a",
|
||||
i->typeid ? t : "n/a",
|
||||
i->sample_spec ? ss : "n/a");
|
||||
|
||||
}
|
||||
|
||||
static void browser_callback(struct pa_browser *b, enum pa_browse_opcode c, const struct pa_browse_info *i, void *userdata) {
|
||||
assert(b && i);
|
||||
|
||||
switch (c) {
|
||||
|
||||
case PA_BROWSE_NEW_SERVER:
|
||||
printf("\n=> new server <%s>\n", i->name);
|
||||
dump_server(i);
|
||||
break;
|
||||
|
||||
case PA_BROWSE_NEW_SINK:
|
||||
printf("\n=> new sink <%s>\n", i->name);
|
||||
dump_server(i);
|
||||
dump_device(i);
|
||||
break;
|
||||
|
||||
case PA_BROWSE_NEW_SOURCE:
|
||||
printf("\n=> new source <%s>\n", i->name);
|
||||
dump_server(i);
|
||||
dump_device(i);
|
||||
break;
|
||||
|
||||
case PA_BROWSE_REMOVE:
|
||||
printf("\n=> removed service <%s>\n", i->name);
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
struct pa_mainloop *mainloop = NULL;
|
||||
struct pa_browser *browser = NULL;
|
||||
int ret = 1, r;
|
||||
|
||||
if (!(mainloop = pa_mainloop_new()))
|
||||
goto finish;
|
||||
|
||||
r = pa_signal_init(pa_mainloop_get_api(mainloop));
|
||||
assert(r == 0);
|
||||
pa_signal_new(SIGINT, exit_signal_callback, NULL);
|
||||
pa_signal_new(SIGTERM, exit_signal_callback, NULL);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
if (!(browser = pa_browser_new(pa_mainloop_get_api(mainloop))))
|
||||
goto finish;
|
||||
|
||||
pa_browser_set_callback(browser, browser_callback, NULL);
|
||||
|
||||
ret = 0;
|
||||
pa_mainloop_run(mainloop, &ret);
|
||||
|
||||
finish:
|
||||
if (mainloop) {
|
||||
pa_signal_done();
|
||||
pa_mainloop_free(mainloop);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
#include <polyp/mainloop-signal.h>
|
||||
#include <polyp/polyplib-version.h>
|
||||
|
||||
#if PA_API_VERSION != 7
|
||||
#if PA_API_VERSION != 8
|
||||
#error Invalid Polypaudio API version
|
||||
#endif
|
||||
|
||||
|
|
@ -290,7 +290,7 @@ static void stdout_callback(struct pa_mainloop_api*a, struct pa_io_event *e, int
|
|||
/* UNIX signal to quit recieved */
|
||||
static void exit_signal_callback(struct pa_mainloop_api*m, struct pa_signal_event *e, int sig, void *userdata) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "Got SIGINT, exiting.\n");
|
||||
fprintf(stderr, "Got signal, exiting.\n");
|
||||
quit(0);
|
||||
|
||||
}
|
||||
|
|
@ -479,6 +479,7 @@ int main(int argc, char *argv[]) {
|
|||
r = pa_signal_init(mainloop_api);
|
||||
assert(r == 0);
|
||||
pa_signal_new(SIGINT, exit_signal_callback, NULL);
|
||||
pa_signal_new(SIGTERM, exit_signal_callback, NULL);
|
||||
pa_signal_new(SIGUSR1, sigusr1_signal_callback, NULL);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@
|
|||
#include <polyp/mainloop-signal.h>
|
||||
#include <polyp/sample.h>
|
||||
|
||||
#if PA_API_VERSION != 7
|
||||
#if PA_API_VERSION != 8
|
||||
#error Invalid Polypaudio API version
|
||||
#endif
|
||||
|
||||
|
|
@ -134,20 +134,22 @@ static void get_server_info_callback(struct pa_context *c, const struct pa_serve
|
|||
"Server Version: %s\n"
|
||||
"Default Sample Specification: %s\n"
|
||||
"Default Sink: %s\n"
|
||||
"Default Source: %s\n",
|
||||
"Default Source: %s\n"
|
||||
"Cookie: %08x\n",
|
||||
i->user_name,
|
||||
i->host_name,
|
||||
i->server_name,
|
||||
i->server_version,
|
||||
s,
|
||||
i->default_sink_name,
|
||||
i->default_source_name);
|
||||
i->default_source_name,
|
||||
i->cookie);
|
||||
|
||||
complete_action();
|
||||
}
|
||||
|
||||
static void get_sink_info_callback(struct pa_context *c, const struct pa_sink_info *i, int is_last, void *userdata) {
|
||||
char s[PA_SAMPLE_SPEC_SNPRINT_MAX];
|
||||
char s[PA_SAMPLE_SPEC_SNPRINT_MAX], tid[5];
|
||||
|
||||
if (is_last < 0) {
|
||||
fprintf(stderr, "Failed to get sink information: %s\n", pa_strerror(pa_context_errno(c)));
|
||||
|
|
@ -170,6 +172,7 @@ static void get_sink_info_callback(struct pa_context *c, const struct pa_sink_in
|
|||
|
||||
printf("*** Sink #%u ***\n"
|
||||
"Name: %s\n"
|
||||
"Type: %s\n"
|
||||
"Description: %s\n"
|
||||
"Sample Specification: %s\n"
|
||||
"Owner Module: %u\n"
|
||||
|
|
@ -178,16 +181,18 @@ static void get_sink_info_callback(struct pa_context *c, const struct pa_sink_in
|
|||
"Latency: %0.0f usec\n",
|
||||
i->index,
|
||||
i->name,
|
||||
pa_typeid_to_string(i->typeid, tid, sizeof(tid)),
|
||||
i->description,
|
||||
s,
|
||||
i->owner_module,
|
||||
i->volume, pa_volume_to_dB(i->volume),
|
||||
i->monitor_source,
|
||||
(double) i->latency);
|
||||
|
||||
}
|
||||
|
||||
static void get_source_info_callback(struct pa_context *c, const struct pa_source_info *i, int is_last, void *userdata) {
|
||||
char s[PA_SAMPLE_SPEC_SNPRINT_MAX], t[32];
|
||||
char s[PA_SAMPLE_SPEC_SNPRINT_MAX], t[32], tid[5];
|
||||
|
||||
if (is_last < 0) {
|
||||
fprintf(stderr, "Failed to get source information: %s\n", pa_strerror(pa_context_errno(c)));
|
||||
|
|
@ -212,18 +217,21 @@ static void get_source_info_callback(struct pa_context *c, const struct pa_sourc
|
|||
|
||||
printf("*** Source #%u ***\n"
|
||||
"Name: %s\n"
|
||||
"Type: %s\n"
|
||||
"Description: %s\n"
|
||||
"Sample Specification: %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->name,
|
||||
i->description,
|
||||
s,
|
||||
i->owner_module,
|
||||
i->monitor_of_sink != PA_INVALID_INDEX ? t : "no",
|
||||
(double) i->latency);
|
||||
|
||||
}
|
||||
|
||||
static void get_module_info_callback(struct pa_context *c, const struct pa_module_info *i, int is_last, void *userdata) {
|
||||
|
|
@ -261,7 +269,7 @@ static void get_module_info_callback(struct pa_context *c, const struct pa_modul
|
|||
}
|
||||
|
||||
static void get_client_info_callback(struct pa_context *c, const struct pa_client_info *i, int is_last, void *userdata) {
|
||||
char t[32];
|
||||
char t[32], tid[5];
|
||||
|
||||
if (is_last < 0) {
|
||||
fprintf(stderr, "Failed to get client information: %s\n", pa_strerror(pa_context_errno(c)));
|
||||
|
|
@ -284,16 +292,16 @@ static void get_client_info_callback(struct pa_context *c, const struct pa_clien
|
|||
|
||||
printf("*** Client #%u ***\n"
|
||||
"Name: %s\n"
|
||||
"Owner Module: %s\n"
|
||||
"Protocol Name: %s\n",
|
||||
"Type: %s\n"
|
||||
"Owner Module: %s\n",
|
||||
i->index,
|
||||
i->name,
|
||||
i->owner_module != PA_INVALID_INDEX ? t : "n/a",
|
||||
i->protocol_name);
|
||||
pa_typeid_to_string(i->typeid, tid, sizeof(tid)),
|
||||
i->owner_module != PA_INVALID_INDEX ? t : "n/a");
|
||||
}
|
||||
|
||||
static void get_sink_input_info_callback(struct pa_context *c, const struct pa_sink_input_info *i, int is_last, void *userdata) {
|
||||
char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX];
|
||||
char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], tid[5];
|
||||
|
||||
if (is_last < 0) {
|
||||
fprintf(stderr, "Failed to get sink input information: %s\n", pa_strerror(pa_context_errno(c)));
|
||||
|
|
@ -318,6 +326,7 @@ static void get_sink_input_info_callback(struct pa_context *c, const struct pa_s
|
|||
|
||||
printf("*** Sink Input #%u ***\n"
|
||||
"Name: %s\n"
|
||||
"Type: %s\n"
|
||||
"Owner Module: %s\n"
|
||||
"Client: %s\n"
|
||||
"Sink: %u\n"
|
||||
|
|
@ -328,6 +337,7 @@ static void get_sink_input_info_callback(struct pa_context *c, const struct pa_s
|
|||
"Resample method: %s\n",
|
||||
i->index,
|
||||
i->name,
|
||||
pa_typeid_to_string(i->typeid, tid, sizeof(tid)),
|
||||
i->owner_module != PA_INVALID_INDEX ? t : "n/a",
|
||||
i->client != PA_INVALID_INDEX ? k : "n/a",
|
||||
i->sink,
|
||||
|
|
@ -338,8 +348,9 @@ static void get_sink_input_info_callback(struct pa_context *c, const struct pa_s
|
|||
i->resample_method ? i->resample_method : "n/a");
|
||||
}
|
||||
|
||||
|
||||
static void get_source_output_info_callback(struct pa_context *c, const struct pa_source_output_info *i, int is_last, void *userdata) {
|
||||
char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX];
|
||||
char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], tid[5];
|
||||
|
||||
if (is_last < 0) {
|
||||
fprintf(stderr, "Failed to get source output information: %s\n", pa_strerror(pa_context_errno(c)));
|
||||
|
|
@ -364,6 +375,7 @@ static void get_source_output_info_callback(struct pa_context *c, const struct p
|
|||
|
||||
printf("*** Source Output #%u ***\n"
|
||||
"Name: %s\n"
|
||||
"Type: %s\n"
|
||||
"Owner Module: %s\n"
|
||||
"Client: %s\n"
|
||||
"Source: %u\n"
|
||||
|
|
@ -373,6 +385,7 @@ static void get_source_output_info_callback(struct pa_context *c, const struct p
|
|||
"Resample method: %s\n",
|
||||
i->index,
|
||||
i->name,
|
||||
pa_typeid_to_string(i->typeid, tid, sizeof(tid)),
|
||||
i->owner_module != PA_INVALID_INDEX ? t : "n/a",
|
||||
i->client != PA_INVALID_INDEX ? k : "n/a",
|
||||
i->source,
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
#include <polyp/mainloop-signal.h>
|
||||
#include <polyp/polyplib-version.h>
|
||||
|
||||
#if PA_API_VERSION != 7
|
||||
#if PA_API_VERSION != 8
|
||||
#error Invalid Polypaudio API version
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@
|
|||
#include "sink-input.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
#define PA_TYPEID_MEMCHUNK PA_TYPEID_MAKE('M', 'C', 'N', 'K')
|
||||
|
||||
static void sink_input_kill(struct pa_sink_input *i) {
|
||||
struct pa_memchunk *c;
|
||||
assert(i && i->userdata);
|
||||
|
|
@ -88,7 +90,7 @@ int pa_play_memchunk(struct pa_sink *sink, const char *name, const struct pa_sam
|
|||
if (volume <= 0)
|
||||
return 0;
|
||||
|
||||
if (!(si = pa_sink_input_new(sink, name, ss, 0, -1)))
|
||||
if (!(si = pa_sink_input_new(sink, PA_TYPEID_MEMCHUNK, name, ss, 0, -1)))
|
||||
return -1;
|
||||
|
||||
si->volume = volume;
|
||||
|
|
|
|||
307
polyp/polyplib-browser.c
Normal file
307
polyp/polyplib-browser.c
Normal file
|
|
@ -0,0 +1,307 @@
|
|||
/* $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 <assert.h>
|
||||
#include <howl.h>
|
||||
|
||||
#include "polyplib-browser.h"
|
||||
#include "xmalloc.h"
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
|
||||
#define SERVICE_NAME_SINK "_polypaudio-sink._tcp."
|
||||
#define SERVICE_NAME_SOURCE "_polypaudio-source._tcp."
|
||||
#define SERVICE_NAME_SERVER "_polypaudio-server._tcp."
|
||||
|
||||
struct pa_browser {
|
||||
int ref;
|
||||
struct pa_mainloop_api *mainloop;
|
||||
|
||||
void (*callback)(struct pa_browser *z, enum pa_browse_opcode c, const struct pa_browse_info *i, void *userdata);
|
||||
void *callback_userdata;
|
||||
|
||||
sw_discovery discovery;
|
||||
struct pa_io_event *io_event;
|
||||
};
|
||||
|
||||
|
||||
static void io_callback(struct pa_mainloop_api*a, struct pa_io_event*e, int fd, enum pa_io_event_flags events, void *userdata) {
|
||||
struct pa_browser *b = userdata;
|
||||
assert(a && b && b->mainloop == a);
|
||||
|
||||
if (events != PA_IO_EVENT_INPUT || sw_discovery_read_socket(b->discovery) != SW_OKAY) {
|
||||
pa_log(__FILE__": connection to HOWL daemon failed.\n");
|
||||
b->mainloop->io_free(b->io_event);
|
||||
b->io_event = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static sw_result resolve_reply(
|
||||
sw_discovery discovery,
|
||||
sw_discovery_oid oid,
|
||||
sw_uint32 interface_index,
|
||||
sw_const_string name,
|
||||
sw_const_string type,
|
||||
sw_const_string domain,
|
||||
sw_ipv4_address address,
|
||||
sw_port port,
|
||||
sw_octets text_record,
|
||||
sw_ulong text_record_len,
|
||||
sw_opaque extra) {
|
||||
|
||||
struct pa_browser *b = extra;
|
||||
struct pa_browse_info i;
|
||||
char ip[256], a[256];
|
||||
enum pa_browse_opcode opcode;
|
||||
int device_found = 0;
|
||||
uint32_t cookie;
|
||||
pa_typeid_t typeid;
|
||||
struct pa_sample_spec ss;
|
||||
int ss_valid = 0;
|
||||
sw_text_record_iterator iterator;
|
||||
int free_iterator = 0;
|
||||
char *c = NULL;
|
||||
|
||||
assert(b);
|
||||
|
||||
sw_discovery_cancel(discovery, oid);
|
||||
|
||||
memset(&i, 0, sizeof(i));
|
||||
i.name = name;
|
||||
|
||||
if (!b->callback)
|
||||
goto fail;
|
||||
|
||||
if (!strcmp(type, SERVICE_NAME_SINK))
|
||||
opcode = PA_BROWSE_NEW_SINK;
|
||||
else if (!strcmp(type, SERVICE_NAME_SOURCE))
|
||||
opcode = PA_BROWSE_NEW_SOURCE;
|
||||
else if (!strcmp(type, SERVICE_NAME_SERVER))
|
||||
opcode = PA_BROWSE_NEW_SERVER;
|
||||
else
|
||||
goto fail;
|
||||
|
||||
|
||||
snprintf(a, sizeof(a), "tcp:%s:%u", sw_ipv4_address_name(address, ip, sizeof(ip)), port);
|
||||
i.server = a;
|
||||
|
||||
if (text_record && text_record_len) {
|
||||
char key[SW_TEXT_RECORD_MAX_LEN];
|
||||
uint8_t val[SW_TEXT_RECORD_MAX_LEN];
|
||||
uint32_t val_len;
|
||||
|
||||
if (sw_text_record_iterator_init(&iterator, text_record, text_record_len) != SW_OKAY) {
|
||||
pa_log("sw_text_record_string_iterator_init() failed.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
free_iterator = 1;
|
||||
|
||||
while (sw_text_record_iterator_next(iterator, key, val, &val_len) == SW_OKAY) {
|
||||
c = pa_xstrndup((char*) val, val_len);
|
||||
|
||||
if (!strcmp(key, "device")) {
|
||||
device_found = 1;
|
||||
pa_xfree((char*) i.device);
|
||||
i.device = c;
|
||||
c = NULL;
|
||||
} else if (!strcmp(key, "server-version")) {
|
||||
pa_xfree((char*) i.server_version);
|
||||
i.server_version = c;
|
||||
c = NULL;
|
||||
} else if (!strcmp(key, "user-name")) {
|
||||
pa_xfree((char*) i.user_name);
|
||||
i.user_name = c;
|
||||
c = NULL;
|
||||
} else if (!strcmp(key, "fqdn")) {
|
||||
pa_xfree((char*) i.fqdn);
|
||||
i.fqdn = c;
|
||||
c = NULL;
|
||||
} else if (!strcmp(key, "cookie")) {
|
||||
|
||||
if (pa_atou(c, &cookie) < 0)
|
||||
goto fail;
|
||||
|
||||
i.cookie = &cookie;
|
||||
} else if (!strcmp(key, "description")) {
|
||||
pa_xfree((char*) i.description);
|
||||
i.description = c;
|
||||
c = NULL;
|
||||
} else if (!strcmp(key, "typeid")) {
|
||||
|
||||
if (pa_atou(c, &typeid) < 0)
|
||||
goto fail;
|
||||
|
||||
i.typeid = &typeid;
|
||||
} else if (!strcmp(key, "channels")) {
|
||||
uint32_t ch;
|
||||
|
||||
if (pa_atou(c, &ch) < 0 || ch <= 0 || ch > 255)
|
||||
goto fail;
|
||||
|
||||
ss.channels = (uint8_t) ch;
|
||||
ss_valid |= 1;
|
||||
|
||||
} else if (!strcmp(key, "rate")) {
|
||||
if (pa_atou(c, &ss.rate) < 0)
|
||||
goto fail;
|
||||
ss_valid |= 2;
|
||||
} else if (!strcmp(key, "format")) {
|
||||
|
||||
if ((ss.format = pa_parse_sample_format(c)) == PA_SAMPLE_INVALID)
|
||||
goto fail;
|
||||
|
||||
ss_valid |= 4;
|
||||
}
|
||||
|
||||
pa_xfree(c);
|
||||
c = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* No device txt record was sent for a sink or source service */
|
||||
if (opcode != PA_BROWSE_NEW_SERVER && !device_found)
|
||||
goto fail;
|
||||
|
||||
if (ss_valid == 7)
|
||||
i.sample_spec = &ss;
|
||||
|
||||
|
||||
b->callback(b, opcode, &i, b->callback_userdata);
|
||||
|
||||
fail:
|
||||
pa_xfree((void*) i.device);
|
||||
pa_xfree((void*) i.fqdn);
|
||||
pa_xfree((void*) i.server_version);
|
||||
pa_xfree((void*) i.user_name);
|
||||
pa_xfree((void*) i.description);
|
||||
pa_xfree(c);
|
||||
|
||||
if (free_iterator)
|
||||
sw_text_record_iterator_fina(iterator);
|
||||
|
||||
|
||||
return SW_OKAY;
|
||||
}
|
||||
|
||||
static sw_result browse_reply(
|
||||
sw_discovery discovery,
|
||||
sw_discovery_oid id,
|
||||
sw_discovery_browse_status status,
|
||||
sw_uint32 interface_index,
|
||||
sw_const_string name,
|
||||
sw_const_string type,
|
||||
sw_const_string domain,
|
||||
sw_opaque extra) {
|
||||
|
||||
struct pa_browser *b = extra;
|
||||
assert(b);
|
||||
|
||||
switch (status) {
|
||||
case SW_DISCOVERY_BROWSE_ADD_SERVICE: {
|
||||
sw_discovery_oid oid;
|
||||
fprintf(stderr, "debug: new service: %s\n", name);
|
||||
|
||||
if (sw_discovery_resolve(b->discovery, 0, name, type, domain, resolve_reply, b, &oid) != SW_OKAY)
|
||||
pa_log("sw_discovery_resolve() failed\n");
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SW_DISCOVERY_BROWSE_REMOVE_SERVICE:
|
||||
if (b->callback) {
|
||||
struct pa_browse_info i;
|
||||
memset(&i, 0, sizeof(i));
|
||||
i.name = name;
|
||||
b->callback(b, PA_BROWSE_REMOVE, &i, b->callback_userdata);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
return SW_OKAY;
|
||||
}
|
||||
|
||||
struct pa_browser *pa_browser_new(struct pa_mainloop_api *mainloop) {
|
||||
struct pa_browser *b;
|
||||
sw_discovery_oid oid;
|
||||
|
||||
b = pa_xmalloc(sizeof(struct pa_browser));
|
||||
b->mainloop = mainloop;
|
||||
b->ref = 1;
|
||||
b->callback = NULL;
|
||||
b->callback_userdata = NULL;
|
||||
|
||||
if (sw_discovery_init(&b->discovery) != SW_OKAY) {
|
||||
pa_log("sw_discovery_init() failed.\n");
|
||||
pa_xfree(b);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sw_discovery_browse(b->discovery, 0, SERVICE_NAME_SERVER, NULL, browse_reply, b, &oid) != SW_OKAY ||
|
||||
sw_discovery_browse(b->discovery, 0, SERVICE_NAME_SINK, NULL, browse_reply, b, &oid) != SW_OKAY ||
|
||||
sw_discovery_browse(b->discovery, 0, SERVICE_NAME_SOURCE, NULL, browse_reply, b, &oid) != SW_OKAY) {
|
||||
|
||||
pa_log("sw_discovery_browse() failed.\n");
|
||||
|
||||
sw_discovery_fina(b->discovery);
|
||||
pa_xfree(b);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
b->io_event = mainloop->io_new(mainloop, sw_discovery_socket(b->discovery), PA_IO_EVENT_INPUT, io_callback, b);
|
||||
return b;
|
||||
}
|
||||
|
||||
static void browser_free(struct pa_browser *b) {
|
||||
assert(b && b->mainloop);
|
||||
|
||||
if (b->io_event)
|
||||
b->mainloop->io_free(b->io_event);
|
||||
|
||||
sw_discovery_fina(b->discovery);
|
||||
pa_xfree(b);
|
||||
}
|
||||
|
||||
struct pa_browser *pa_browser_ref(struct pa_browser *b) {
|
||||
assert(b && b->ref >= 1);
|
||||
b->ref++;
|
||||
return b;
|
||||
}
|
||||
|
||||
void pa_browser_unref(struct pa_browser *b) {
|
||||
assert(b && b->ref >= 1);
|
||||
|
||||
if ((-- (b->ref)) <= 0)
|
||||
browser_free(b);
|
||||
}
|
||||
|
||||
void pa_browser_set_callback(struct pa_browser *b, void (*cb)(struct pa_browser *z, enum pa_browse_opcode c, const struct pa_browse_info *i, void* userdata), void *userdata) {
|
||||
assert(b);
|
||||
|
||||
b->callback = cb;
|
||||
b->callback_userdata = userdata;
|
||||
}
|
||||
65
polyp/polyplib-browser.h
Normal file
65
polyp/polyplib-browser.h
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
#ifndef foopolyplibbrowserhfoo
|
||||
#define foopolyplibbrowserhfoo
|
||||
|
||||
/* $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/mainloop-api.h>
|
||||
#include <polyp/sample.h>
|
||||
#include <polyp/cdecl.h>
|
||||
#include <polyp/typeid.h>
|
||||
|
||||
PA_C_DECL_BEGIN
|
||||
|
||||
struct pa_browser;
|
||||
|
||||
enum pa_browse_opcode {
|
||||
PA_BROWSE_NEW_SERVER,
|
||||
PA_BROWSE_NEW_SINK,
|
||||
PA_BROWSE_NEW_SOURCE,
|
||||
PA_BROWSE_REMOVE
|
||||
};
|
||||
|
||||
struct pa_browser *pa_browser_new(struct pa_mainloop_api *mainloop);
|
||||
struct pa_browser *pa_browser_ref(struct pa_browser *z);
|
||||
void pa_browser_unref(struct pa_browser *z);
|
||||
|
||||
struct pa_browse_info {
|
||||
/* Unique service name */
|
||||
const char *name; /* always available */
|
||||
|
||||
/* Server info */
|
||||
const char *server; /* always available */
|
||||
const char *server_version, *user_name, *fqdn; /* optional */
|
||||
const uint32_t *cookie; /* optional */
|
||||
|
||||
/* Device info */
|
||||
const char *device; /* always available when this information is of a sink/source */
|
||||
const char *description; /* optional */
|
||||
const pa_typeid_t *typeid; /* optional */
|
||||
const struct pa_sample_spec *sample_spec; /* optional */
|
||||
};
|
||||
|
||||
void pa_browser_set_callback(struct pa_browser *z, void (*cb)(struct pa_browser *z, enum pa_browse_opcode c, const struct pa_browse_info *i, void *userdata), void *userdata);
|
||||
|
||||
PA_C_DECL_END
|
||||
|
||||
#endif
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#ifndef foopolyplibcontexthfoo
|
||||
#define foopolyplibcontexthfoo
|
||||
|
||||
|
|
@ -23,11 +22,11 @@
|
|||
USA.
|
||||
***/
|
||||
|
||||
#include "sample.h"
|
||||
#include "polyplib-def.h"
|
||||
#include "mainloop-api.h"
|
||||
#include "cdecl.h"
|
||||
#include "polyplib-operation.h"
|
||||
#include <polyp/sample.h>
|
||||
#include <polyp/polyplib-def.h>
|
||||
#include <polyp/mainloop-api.h>
|
||||
#include <polyp/cdecl.h>
|
||||
#include <polyp/polyplib-operation.h>
|
||||
|
||||
/** \file
|
||||
* Connection contexts for asynchrononous communication with a
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@
|
|||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "cdecl.h"
|
||||
#include "sample.h"
|
||||
#include <polyp/cdecl.h>
|
||||
#include <polyp/sample.h>
|
||||
|
||||
/** \file
|
||||
* Global definitions */
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ static void context_get_server_info_callback(struct pa_pdispatch *pd, uint32_t c
|
|||
pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 0 ||
|
||||
pa_tagstruct_gets(t, &i.default_sink_name) < 0 ||
|
||||
pa_tagstruct_gets(t, &i.default_source_name) < 0 ||
|
||||
pa_tagstruct_getu32(t, &i.cookie) < 0 ||
|
||||
!pa_tagstruct_eof(t)) {
|
||||
|
||||
pa_context_fail(o->context, PA_ERROR_PROTOCOL);
|
||||
|
|
@ -130,7 +131,9 @@ static void context_get_sink_info_callback(struct pa_pdispatch *pd, uint32_t com
|
|||
pa_tagstruct_getu32(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_get_usec(t, &i.latency) < 0 ||
|
||||
pa_tagstruct_getu32(t, &i.typeid) < 0) {
|
||||
|
||||
pa_context_fail(o->context, PA_ERROR_PROTOCOL);
|
||||
goto finish;
|
||||
}
|
||||
|
|
@ -222,7 +225,8 @@ static void context_get_source_info_callback(struct pa_pdispatch *pd, uint32_t c
|
|||
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_get_usec(t, &i.latency) < 0 ||
|
||||
pa_tagstruct_getu32(t, &i.typeid) < 0) {
|
||||
|
||||
pa_context_fail(o->context, PA_ERROR_PROTOCOL);
|
||||
goto finish;
|
||||
|
|
@ -310,8 +314,8 @@ static void context_get_client_info_callback(struct pa_pdispatch *pd, uint32_t c
|
|||
|
||||
if (pa_tagstruct_getu32(t, &i.index) < 0 ||
|
||||
pa_tagstruct_gets(t, &i.name) < 0 ||
|
||||
pa_tagstruct_gets(t, &i.protocol_name) < 0 ||
|
||||
pa_tagstruct_getu32(t, &i.owner_module) < 0) {
|
||||
pa_tagstruct_getu32(t, &i.owner_module) < 0 ||
|
||||
pa_tagstruct_getu32(t, &i.typeid) < 0 ) {
|
||||
pa_context_fail(o->context, PA_ERROR_PROTOCOL);
|
||||
goto finish;
|
||||
}
|
||||
|
|
@ -450,7 +454,9 @@ static void context_get_sink_input_info_callback(struct pa_pdispatch *pd, uint32
|
|||
pa_tagstruct_getu32(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_gets(t, &i.resample_method) < 0 ||
|
||||
pa_tagstruct_getu32(t, &i.typeid) < 0) {
|
||||
|
||||
pa_context_fail(o->context, PA_ERROR_PROTOCOL);
|
||||
goto finish;
|
||||
}
|
||||
|
|
@ -521,7 +527,9 @@ static void context_get_source_output_info_callback(struct pa_pdispatch *pd, uin
|
|||
pa_tagstruct_get_sample_spec(t, &i.sample_spec) < 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_gets(t, &i.resample_method) < 0 ||
|
||||
pa_tagstruct_getu32(t, &i.typeid) < 0) {
|
||||
|
||||
pa_context_fail(o->context, PA_ERROR_PROTOCOL);
|
||||
goto finish;
|
||||
}
|
||||
|
|
@ -659,6 +667,7 @@ static void context_get_sample_info_callback(struct pa_pdispatch *pd, uint32_t c
|
|||
pa_tagstruct_getu32(t, &i.bytes) < 0 ||
|
||||
pa_tagstruct_get_boolean(t, &i.lazy) < 0 ||
|
||||
pa_tagstruct_gets(t, &i.filename) < 0) {
|
||||
|
||||
pa_context_fail(o->context, PA_ERROR_PROTOCOL);
|
||||
goto finish;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,9 +24,10 @@
|
|||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "polyplib-operation.h"
|
||||
#include "polyplib-context.h"
|
||||
#include "cdecl.h"
|
||||
#include <polyp/polyplib-operation.h>
|
||||
#include <polyp/polyplib-context.h>
|
||||
#include <polyp/cdecl.h>
|
||||
#include <polyp/typeid.h>
|
||||
|
||||
/** \file
|
||||
*
|
||||
|
|
@ -57,6 +58,7 @@ struct pa_sink_info {
|
|||
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 */
|
||||
};
|
||||
|
||||
/** Get information about a sink by its name */
|
||||
|
|
@ -78,6 +80,7 @@ struct pa_source_info {
|
|||
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 */
|
||||
};
|
||||
|
||||
/** Get information about a source by its name */
|
||||
|
|
@ -97,7 +100,8 @@ struct pa_server_info {
|
|||
const char *server_name; /**< Server package name (usually "polypaudio") */
|
||||
struct 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*/
|
||||
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 */
|
||||
};
|
||||
|
||||
/** Get some information about the server */
|
||||
|
|
@ -123,7 +127,7 @@ 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 */
|
||||
const char *protocol_name; /**< A string describing the protocol name this client is connected over (i.e. "ESOUND", "NATIVE", "SIMPLE") */
|
||||
pa_typeid_t typeid; /**< Implementation type. \since 0.8 */
|
||||
};
|
||||
|
||||
/** Get information about a client by its index */
|
||||
|
|
@ -144,6 +148,7 @@ struct pa_sink_input_info {
|
|||
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 */
|
||||
};
|
||||
|
||||
/** Get some information about a sink input by its index */
|
||||
|
|
@ -163,6 +168,7 @@ struct pa_source_output_info {
|
|||
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 */
|
||||
};
|
||||
|
||||
/** Get information about a source output by its index */
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@
|
|||
USA.
|
||||
***/
|
||||
|
||||
#include "cdecl.h"
|
||||
#include "polyplib-def.h"
|
||||
#include <polyp/cdecl.h>
|
||||
#include <polyp/polyplib-def.h>
|
||||
|
||||
/** \file
|
||||
* Asynchronous operations */
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "polyplib-context.h"
|
||||
#include "polyplib-stream.h"
|
||||
#include "cdecl.h"
|
||||
#include <polyp/polyplib-context.h>
|
||||
#include <polyp/polyplib-stream.h>
|
||||
#include <polyp/cdecl.h>
|
||||
|
||||
/** \file
|
||||
* All sample cache related routines */
|
||||
|
|
|
|||
|
|
@ -24,10 +24,10 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "sample.h"
|
||||
#include "polyplib-def.h"
|
||||
#include "cdecl.h"
|
||||
#include "polyplib-operation.h"
|
||||
#include <polyp/sample.h>
|
||||
#include <polyp/polyplib-def.h>
|
||||
#include <polyp/cdecl.h>
|
||||
#include <polyp/polyplib-operation.h>
|
||||
|
||||
/** \file
|
||||
* Audio streams for input, output and sample upload */
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@
|
|||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "polyplib-def.h"
|
||||
#include "polyplib-context.h"
|
||||
#include "cdecl.h"
|
||||
#include <polyp/polyplib-def.h>
|
||||
#include <polyp/polyplib-context.h>
|
||||
#include <polyp/cdecl.h>
|
||||
|
||||
/** \file
|
||||
* Daemon introspection event subscription subsystem. Use this
|
||||
|
|
|
|||
|
|
@ -22,16 +22,16 @@
|
|||
USA.
|
||||
***/
|
||||
|
||||
#include "cdecl.h"
|
||||
#include "mainloop-api.h"
|
||||
#include "sample.h"
|
||||
#include "polyplib-def.h"
|
||||
#include "polyplib-context.h"
|
||||
#include "polyplib-stream.h"
|
||||
#include "polyplib-introspect.h"
|
||||
#include "polyplib-subscribe.h"
|
||||
#include "polyplib-scache.h"
|
||||
#include "polyplib-version.h"
|
||||
#include <polyp/cdecl.h>
|
||||
#include <polyp/mainloop-api.h>
|
||||
#include <polyp/sample.h>
|
||||
#include <polyp/polyplib-def.h>
|
||||
#include <polyp/polyplib-context.h>
|
||||
#include <polyp/polyplib-stream.h>
|
||||
#include <polyp/polyplib-introspect.h>
|
||||
#include <polyp/polyplib-subscribe.h>
|
||||
#include <polyp/polyplib-scache.h>
|
||||
#include <polyp/polyplib-version.h>
|
||||
|
||||
/** \file
|
||||
* Include all polyplib header file at once. The following files are included: \ref mainloop-api.h, \ref sample.h,
|
||||
|
|
|
|||
|
|
@ -63,6 +63,8 @@
|
|||
|
||||
#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 {
|
||||
|
|
@ -320,7 +322,7 @@ static int esd_proto_stream_play(struct connection *c, esd_proto_t request, cons
|
|||
|
||||
assert(!c->sink_input && !c->input_memblockq);
|
||||
|
||||
if (!(c->sink_input = pa_sink_input_new(sink, name, &ss, 0, -1))) {
|
||||
if (!(c->sink_input = pa_sink_input_new(sink, PA_TYPEID_ESOUND, name, &ss, 0, -1))) {
|
||||
pa_log(__FILE__": failed to create sink input.\n");
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -392,7 +394,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, name, &ss, -1))) {
|
||||
if (!(c->source_output = pa_source_output_new(source, PA_TYPEID_ESOUND, name, &ss, -1))) {
|
||||
pa_log(__FILE__": failed to create source output\n");
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1058,7 +1060,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo
|
|||
|
||||
pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname));
|
||||
assert(p->core);
|
||||
c->client = pa_client_new(p->core, "ESOUND", cname);
|
||||
c->client = pa_client_new(p->core, PA_TYPEID_ESOUND, cname);
|
||||
assert(c->client);
|
||||
c->client->owner = p->module;
|
||||
c->client->kill = client_kill_cb;
|
||||
|
|
|
|||
|
|
@ -56,6 +56,8 @@
|
|||
/* 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;
|
||||
|
||||
|
|
@ -272,7 +274,7 @@ static struct record_stream* record_stream_new(struct connection *c, struct pa_s
|
|||
size_t base;
|
||||
assert(c && source && ss && name && maxlength);
|
||||
|
||||
if (!(source_output = pa_source_output_new(source, name, ss, -1)))
|
||||
if (!(source_output = pa_source_output_new(source, PA_TYPEID_NATIVE, name, ss, -1)))
|
||||
return NULL;
|
||||
|
||||
s = pa_xmalloc(sizeof(struct record_stream));
|
||||
|
|
@ -316,7 +318,7 @@ static struct playback_stream* playback_stream_new(struct connection *c, struct
|
|||
struct pa_sink_input *sink_input;
|
||||
assert(c && sink && ss && name && maxlength);
|
||||
|
||||
if (!(sink_input = pa_sink_input_new(sink, name, ss, 0, -1)))
|
||||
if (!(sink_input = pa_sink_input_new(sink, PA_TYPEID_NATIVE, name, ss, 0, -1)))
|
||||
return NULL;
|
||||
|
||||
s = pa_xmalloc(sizeof(struct playback_stream));
|
||||
|
|
@ -1118,6 +1120,7 @@ static void sink_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink *sink) {
|
|||
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);
|
||||
}
|
||||
|
||||
static void source_fill_tagstruct(struct pa_tagstruct *t, struct pa_source *source) {
|
||||
|
|
@ -1130,14 +1133,15 @@ static void source_fill_tagstruct(struct pa_tagstruct *t, struct pa_source *sour
|
|||
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);
|
||||
}
|
||||
|
||||
static void client_fill_tagstruct(struct pa_tagstruct *t, struct pa_client *client) {
|
||||
assert(t && client);
|
||||
pa_tagstruct_putu32(t, client->index);
|
||||
pa_tagstruct_puts(t, client->name);
|
||||
pa_tagstruct_puts(t, client->protocol_name);
|
||||
pa_tagstruct_putu32(t, client->owner ? client->owner->index : (uint32_t) -1);
|
||||
pa_tagstruct_putu32(t, client->typeid);
|
||||
}
|
||||
|
||||
static void module_fill_tagstruct(struct pa_tagstruct *t, struct pa_module *module) {
|
||||
|
|
@ -1161,6 +1165,7 @@ static void sink_input_fill_tagstruct(struct pa_tagstruct *t, struct pa_sink_inp
|
|||
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);
|
||||
}
|
||||
|
||||
static void source_output_fill_tagstruct(struct pa_tagstruct *t, struct pa_source_output *s) {
|
||||
|
|
@ -1174,6 +1179,7 @@ static void source_output_fill_tagstruct(struct pa_tagstruct *t, struct pa_sourc
|
|||
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);
|
||||
}
|
||||
|
||||
static void scache_fill_tagstruct(struct pa_tagstruct *t, struct pa_scache_entry *e) {
|
||||
|
|
@ -1366,6 +1372,9 @@ static void command_get_server_info(struct pa_pdispatch *pd, uint32_t command, u
|
|||
pa_tagstruct_puts(reply, n);
|
||||
n = pa_namereg_get_default_source_name(c->protocol->core);
|
||||
pa_tagstruct_puts(reply, n);
|
||||
|
||||
pa_tagstruct_putu32(reply, c->protocol->core->cookie);
|
||||
|
||||
pa_pstream_send_tagstruct(c->pstream, reply);
|
||||
}
|
||||
|
||||
|
|
@ -2022,7 +2031,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo
|
|||
|
||||
c->protocol = p;
|
||||
assert(p->core);
|
||||
c->client = pa_client_new(p->core, "NATIVE", "Client");
|
||||
c->client = pa_client_new(p->core, PA_TYPEID_NATIVE, "Client");
|
||||
assert(c->client);
|
||||
c->client->kill = client_kill_cb;
|
||||
c->client->userdata = c;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@
|
|||
/* 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 {
|
||||
struct pa_protocol_simple *protocol;
|
||||
struct pa_iochannel *io;
|
||||
|
|
@ -308,7 +310,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo
|
|||
c->playback.fragment_size = 0;
|
||||
|
||||
pa_iochannel_socket_peer_to_string(io, cname, sizeof(cname));
|
||||
c->client = pa_client_new(p->core, "SIMPLE", cname);
|
||||
c->client = pa_client_new(p->core, PA_TYPEID_SIMPLE, cname);
|
||||
assert(c->client);
|
||||
c->client->owner = p->module;
|
||||
c->client->kill = client_kill_cb;
|
||||
|
|
@ -323,7 +325,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (!(c->sink_input = pa_sink_input_new(sink, c->client->name, &p->sample_spec, 0, -1))) {
|
||||
if (!(c->sink_input = pa_sink_input_new(sink, PA_TYPEID_SIMPLE, c->client->name, &p->sample_spec, 0, -1))) {
|
||||
pa_log(__FILE__": Failed to create sink input.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
|
@ -353,7 +355,7 @@ static void on_connection(struct pa_socket_server*s, struct pa_iochannel *io, vo
|
|||
goto fail;
|
||||
}
|
||||
|
||||
c->source_output = pa_source_output_new(source, c->client->name, &p->sample_spec, -1);
|
||||
c->source_output = pa_source_output_new(source, PA_TYPEID_SIMPLE, c->client->name, &p->sample_spec, -1);
|
||||
if (!c->source_output) {
|
||||
pa_log(__FILE__": Failed to create source output.\n");
|
||||
goto fail;
|
||||
|
|
|
|||
61
polyp/random.c
Normal file
61
polyp/random.c
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/* $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.1 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
|
||||
Lesser 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 <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "random.h"
|
||||
#include "util.h"
|
||||
#include "log.h"
|
||||
|
||||
#define RANDOM_DEVICE "/dev/urandom"
|
||||
|
||||
void pa_random(void *ret_data, size_t length) {
|
||||
int fd;
|
||||
ssize_t r = 0;
|
||||
assert(ret_data && length);
|
||||
|
||||
if ((fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) {
|
||||
|
||||
if ((r = pa_loop_read(fd, ret_data, length)) < 0 || (size_t) r != length)
|
||||
pa_log_error(__FILE__": failed to read entropy from '%s'\n", RANDOM_DEVICE);
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if ((size_t) r != length) {
|
||||
uint8_t *p;
|
||||
size_t l;
|
||||
|
||||
pa_log_warn(__FILE__": WARNING: Failed to open entropy device '"RANDOM_DEVICE"': %s"
|
||||
", falling back to unsecure pseudo RNG.\n", strerror(errno));
|
||||
|
||||
srandom(time(NULL));
|
||||
|
||||
for (p = ret_data, l = length; l > 0; p++, l--)
|
||||
*p = (uint8_t) random();
|
||||
}
|
||||
}
|
||||
27
polyp/random.h
Normal file
27
polyp/random.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef foorandomhfoo
|
||||
#define foorandomhfoo
|
||||
|
||||
/* $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.1 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
|
||||
Lesser 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.
|
||||
***/
|
||||
|
||||
void pa_random(void *ret_data, size_t length);
|
||||
|
||||
#endif
|
||||
|
|
@ -163,23 +163,23 @@ void pa_bytes_snprint(char *s, size_t l, unsigned v) {
|
|||
|
||||
enum pa_sample_format pa_parse_sample_format(const char *format) {
|
||||
|
||||
if (strcmp(format, "s16le") == 0)
|
||||
if (strcasecmp(format, "s16le") == 0)
|
||||
return PA_SAMPLE_S16LE;
|
||||
else if (strcmp(format, "s16be") == 0)
|
||||
else if (strcasecmp(format, "s16be") == 0)
|
||||
return PA_SAMPLE_S16BE;
|
||||
else if (strcmp(format, "s16ne") == 0 || strcmp(format, "s16") == 0 || strcmp(format, "16") == 0)
|
||||
else if (strcasecmp(format, "s16ne") == 0 || strcasecmp(format, "s16") == 0 || strcasecmp(format, "16") == 0)
|
||||
return PA_SAMPLE_S16NE;
|
||||
else if (strcmp(format, "u8") == 0 || strcmp(format, "8") == 0)
|
||||
else if (strcasecmp(format, "u8") == 0 || strcasecmp(format, "8") == 0)
|
||||
return PA_SAMPLE_U8;
|
||||
else if (strcmp(format, "float32") == 0 || strcmp(format, "float32ne") == 0)
|
||||
else if (strcasecmp(format, "float32") == 0 || strcasecmp(format, "float32ne") == 0)
|
||||
return PA_SAMPLE_FLOAT32;
|
||||
else if (strcmp(format, "float32le") == 0)
|
||||
else if (strcasecmp(format, "float32le") == 0)
|
||||
return PA_SAMPLE_FLOAT32LE;
|
||||
else if (strcmp(format, "float32be") == 0)
|
||||
else if (strcasecmp(format, "float32be") == 0)
|
||||
return PA_SAMPLE_FLOAT32BE;
|
||||
else if (strcmp(format, "ulaw") == 0)
|
||||
else if (strcasecmp(format, "ulaw") == 0)
|
||||
return PA_SAMPLE_ULAW;
|
||||
else if (strcmp(format, "alaw") == 0)
|
||||
else if (strcasecmp(format, "alaw") == 0)
|
||||
return PA_SAMPLE_ALAW;
|
||||
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
#include <sys/types.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "cdecl.h"
|
||||
#include <polyp/cdecl.h>
|
||||
|
||||
/** \file
|
||||
* Constants and routines for sample type handling */
|
||||
|
|
@ -86,7 +86,7 @@ int pa_sample_spec_valid(const struct pa_sample_spec *spec);
|
|||
/** Return non-zero when the two sample type specifications match */
|
||||
int pa_sample_spec_equal(const struct pa_sample_spec*a, const struct pa_sample_spec*b);
|
||||
|
||||
/* Return a descriptive string for the specified sample format. \since 0.7.1 */
|
||||
/* Return a descriptive string for the specified sample format. \since 0.8 */
|
||||
const char *pa_sample_format_to_string(enum pa_sample_format f);
|
||||
|
||||
/** Maximum required string length for pa_sample_spec_snprint() */
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
#define CONVERT_BUFFER_LENGTH 4096
|
||||
|
||||
struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, const struct pa_sample_spec *spec, int variable_rate, int resample_method) {
|
||||
struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, pa_typeid_t typeid, const char *name, const struct pa_sample_spec *spec, int variable_rate, int resample_method) {
|
||||
struct pa_sink_input *i;
|
||||
struct pa_resampler *resampler = NULL;
|
||||
int r;
|
||||
|
|
@ -59,6 +59,7 @@ struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, con
|
|||
i->ref = 1;
|
||||
i->state = PA_SINK_INPUT_RUNNING;
|
||||
i->name = pa_xstrdup(name);
|
||||
i->typeid = typeid;
|
||||
i->client = NULL;
|
||||
i->owner = NULL;
|
||||
i->sink = s;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ struct pa_sink_input {
|
|||
enum pa_sink_input_state state;
|
||||
|
||||
uint32_t index;
|
||||
pa_typeid_t typeid;
|
||||
|
||||
char *name;
|
||||
struct pa_module *owner;
|
||||
|
|
@ -64,7 +65,7 @@ struct pa_sink_input {
|
|||
struct pa_resampler *resampler;
|
||||
};
|
||||
|
||||
struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, const char *name, const struct pa_sample_spec *spec, int variable_rate, int resample_method);
|
||||
struct pa_sink_input* pa_sink_input_new(struct pa_sink *s, pa_typeid_t typeid, const char *name, const struct pa_sample_spec *spec, int variable_rate, int resample_method);
|
||||
void pa_sink_input_unref(struct pa_sink_input* i);
|
||||
struct pa_sink_input* pa_sink_input_ref(struct pa_sink_input* i);
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
|
||||
#define MAX_MIX_CHANNELS 32
|
||||
|
||||
struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, const struct pa_sample_spec *spec) {
|
||||
struct pa_sink* pa_sink_new(struct pa_core *core, pa_typeid_t typeid, const char *name, int fail, const struct pa_sample_spec *spec) {
|
||||
struct pa_sink *s;
|
||||
char *n = NULL;
|
||||
char st[256];
|
||||
|
|
@ -55,6 +55,7 @@ struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, co
|
|||
|
||||
s->name = pa_xstrdup(name);
|
||||
s->description = NULL;
|
||||
s->typeid = typeid;
|
||||
|
||||
s->ref = 1;
|
||||
s->state = PA_SINK_RUNNING;
|
||||
|
|
@ -65,7 +66,7 @@ struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, co
|
|||
s->inputs = pa_idxset_new(NULL, NULL);
|
||||
|
||||
n = pa_sprintf_malloc("%s_monitor", name);
|
||||
s->monitor_source = pa_source_new(core, n, 0, spec);
|
||||
s->monitor_source = pa_source_new(core, typeid, n, 0, spec);
|
||||
assert(s->monitor_source);
|
||||
pa_xfree(n);
|
||||
s->monitor_source->monitor_of = s;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ struct pa_sink;
|
|||
#include "sample.h"
|
||||
#include "idxset.h"
|
||||
#include "source.h"
|
||||
#include "typeid.h"
|
||||
|
||||
#define PA_MAX_INPUTS_PER_SINK 6
|
||||
|
||||
|
|
@ -43,6 +44,7 @@ struct pa_sink {
|
|||
enum pa_sink_state state;
|
||||
|
||||
uint32_t index;
|
||||
pa_typeid_t typeid;
|
||||
|
||||
char *name, *description;
|
||||
struct pa_module *owner;
|
||||
|
|
@ -59,7 +61,7 @@ struct pa_sink {
|
|||
void *userdata;
|
||||
};
|
||||
|
||||
struct pa_sink* pa_sink_new(struct pa_core *core, const char *name, int fail, const struct pa_sample_spec *spec);
|
||||
struct pa_sink* pa_sink_new(struct pa_core *core, pa_typeid_t typeid, const char *name, int fail, const struct pa_sample_spec *spec);
|
||||
void pa_sink_disconnect(struct pa_sink* s);
|
||||
void pa_sink_unref(struct pa_sink*s);
|
||||
struct pa_sink* pa_sink_ref(struct pa_sink *s);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "log.h"
|
||||
|
||||
#define BUF_SIZE (1024*10)
|
||||
#define PA_TYPEID_SOUND_FILE PA_TYPEID_MAKE('S', 'N', 'D', 'F')
|
||||
|
||||
struct userdata {
|
||||
SNDFILE *sndfile;
|
||||
|
|
@ -160,7 +161,7 @@ int pa_play_file(struct pa_sink *sink, const char *fname, pa_volume_t volume) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (!(u->sink_input = pa_sink_input_new(sink, fname, &ss, 0, -1)))
|
||||
if (!(u->sink_input = pa_sink_input_new(sink, PA_TYPEID_SOUND_FILE, fname, &ss, 0, -1)))
|
||||
goto fail;
|
||||
|
||||
u->sink_input->volume = volume;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
#include "subscribe.h"
|
||||
#include "log.h"
|
||||
|
||||
struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *name, const struct pa_sample_spec *spec, int resample_method) {
|
||||
struct pa_source_output* pa_source_output_new(struct pa_source *s, pa_typeid_t typeid, const char *name, const struct pa_sample_spec *spec, int resample_method) {
|
||||
struct pa_source_output *o;
|
||||
struct pa_resampler *resampler = NULL;
|
||||
int r;
|
||||
|
|
@ -56,6 +56,8 @@ struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *n
|
|||
o->ref = 1;
|
||||
o->state = PA_SOURCE_OUTPUT_RUNNING;
|
||||
o->name = pa_xstrdup(name);
|
||||
o->typeid = typeid;
|
||||
|
||||
o->client = NULL;
|
||||
o->owner = NULL;
|
||||
o->source = s;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ struct pa_source_output {
|
|||
enum pa_source_output_state state;
|
||||
|
||||
uint32_t index;
|
||||
pa_typeid_t typeid;
|
||||
|
||||
char *name;
|
||||
struct pa_module *owner;
|
||||
|
|
@ -58,7 +59,7 @@ struct pa_source_output {
|
|||
void *userdata;
|
||||
};
|
||||
|
||||
struct pa_source_output* pa_source_output_new(struct pa_source *s, const char *name, const struct pa_sample_spec *spec, int resample_method);
|
||||
struct pa_source_output* pa_source_output_new(struct pa_source *s, pa_typeid_t typeid, const char *name, const struct pa_sample_spec *spec, int resample_method);
|
||||
void pa_source_output_unref(struct pa_source_output* o);
|
||||
struct pa_source_output* pa_source_output_ref(struct pa_source_output *o);
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
#include "subscribe.h"
|
||||
#include "log.h"
|
||||
|
||||
struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail, const struct pa_sample_spec *spec) {
|
||||
struct pa_source* pa_source_new(struct pa_core *core, pa_typeid_t typeid, const char *name, int fail, const struct pa_sample_spec *spec) {
|
||||
struct pa_source *s;
|
||||
char st[256];
|
||||
int r;
|
||||
|
|
@ -53,6 +53,7 @@ struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail
|
|||
|
||||
s->name = pa_xstrdup(name);
|
||||
s->description = NULL;
|
||||
s->typeid = typeid;
|
||||
|
||||
s->owner = NULL;
|
||||
s->core = core;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ struct pa_source;
|
|||
#include "memblock.h"
|
||||
#include "memchunk.h"
|
||||
#include "sink.h"
|
||||
#include "typeid.h"
|
||||
|
||||
#define PA_MAX_OUTPUTS_PER_SOURCE 16
|
||||
|
||||
|
|
@ -44,6 +45,7 @@ struct pa_source {
|
|||
enum pa_source_state state;
|
||||
|
||||
uint32_t index;
|
||||
pa_typeid_t typeid;
|
||||
|
||||
char *name, *description;
|
||||
struct pa_module *owner;
|
||||
|
|
@ -57,7 +59,7 @@ struct pa_source {
|
|||
void *userdata;
|
||||
};
|
||||
|
||||
struct pa_source* pa_source_new(struct pa_core *core, const char *name, int fail, const struct pa_sample_spec *spec);
|
||||
struct pa_source* pa_source_new(struct pa_core *core, pa_typeid_t typeid, const char *name, int fail, const struct pa_sample_spec *spec);
|
||||
void pa_source_disconnect(struct pa_source *s);
|
||||
void pa_source_unref(struct pa_source *s);
|
||||
struct pa_source* pa_source_ref(struct pa_source *c);
|
||||
|
|
|
|||
33
polyp/typeid.c
Normal file
33
polyp/typeid.c
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/* $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.1 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
|
||||
Lesser 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 <stdio.h>
|
||||
|
||||
#include "typeid.h"
|
||||
|
||||
char *pa_typeid_to_string(pa_typeid_t id, char *ret_s, size_t length) {
|
||||
if (id == PA_TYPEID_UNKNOWN)
|
||||
snprintf(ret_s, length, "????");
|
||||
else
|
||||
snprintf(ret_s, length, "%c%c%c%c", (char) (id >> 24), (char) (id >> 16), (char) (id >> 8), (char) (id));
|
||||
|
||||
return ret_s;
|
||||
}
|
||||
40
polyp/typeid.h
Normal file
40
polyp/typeid.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef footypeidhfoo
|
||||
#define footypeidhfoo
|
||||
|
||||
/* $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.1 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
|
||||
Lesser 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 <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef uint32_t pa_typeid_t;
|
||||
|
||||
#define PA_TYPEID_UNKNOWN ((pa_typeid_t) -1)
|
||||
|
||||
char *pa_typeid_to_string(pa_typeid_t id, char *ret_s, size_t length);
|
||||
|
||||
#define PA_TYPEID_MAKE(a,b,c,d) (\
|
||||
(((pa_typeid_t) a & 0xFF) << 24) | \
|
||||
(((pa_typeid_t) b & 0xFF) << 16) | \
|
||||
(((pa_typeid_t) c & 0xFF) << 8) | \
|
||||
(((pa_typeid_t) d & 0xFF)))
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue