2004-12-12 22:58:53 +00:00
|
|
|
/***
|
2006-06-19 21:53:48 +00:00
|
|
|
This file is part of PulseAudio.
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2007-02-13 15:35:19 +00:00
|
|
|
Copyright 2004-2006 Lennart Poettering
|
|
|
|
|
|
2006-06-19 21:53:48 +00:00
|
|
|
PulseAudio is free software; you can redistribute it and/or modify
|
2004-12-12 22:58:53 +00:00
|
|
|
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.
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2006-06-19 21:53:48 +00:00
|
|
|
PulseAudio is distributed in the hope that it will be useful, but
|
2004-12-12 22:58:53 +00:00
|
|
|
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.
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2004-12-12 22:58:53 +00:00
|
|
|
You should have received a copy of the GNU Lesser General Public
|
2006-06-19 21:53:48 +00:00
|
|
|
License along with PulseAudio; if not, write to the Free Software
|
2004-12-12 22:58:53 +00:00
|
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
|
|
|
USA.
|
|
|
|
|
***/
|
|
|
|
|
|
2007-01-04 13:43:45 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
#include "config.h"
|
|
|
|
|
#endif
|
2006-06-21 14:05:15 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
#include <avahi-client/lookup.h>
|
|
|
|
|
#include <avahi-common/domain.h>
|
|
|
|
|
#include <avahi-common/error.h>
|
2004-12-12 22:58:53 +00:00
|
|
|
|
2006-06-19 21:53:48 +00:00
|
|
|
#include <pulse/xmalloc.h>
|
2006-05-17 16:34:18 +00:00
|
|
|
|
2006-06-19 21:53:48 +00:00
|
|
|
#include <pulsecore/log.h>
|
|
|
|
|
#include <pulsecore/core-util.h>
|
2006-07-13 17:33:44 +00:00
|
|
|
#include <pulsecore/avahi-wrap.h>
|
2007-10-28 19:13:50 +00:00
|
|
|
#include <pulsecore/refcnt.h>
|
|
|
|
|
#include <pulsecore/macro.h>
|
2006-07-13 17:33:44 +00:00
|
|
|
|
2006-02-17 12:10:58 +00:00
|
|
|
#include "browser.h"
|
|
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
#define SERVICE_TYPE_SINK "_pulse-sink._tcp."
|
|
|
|
|
#define SERVICE_TYPE_SOURCE "_pulse-source._tcp."
|
|
|
|
|
#define SERVICE_TYPE_SERVER "_pulse-server._tcp."
|
2004-12-12 22:58:53 +00:00
|
|
|
|
2006-02-22 20:11:56 +00:00
|
|
|
struct pa_browser {
|
2007-10-28 19:13:50 +00:00
|
|
|
PA_REFCNT_DECLARE;
|
|
|
|
|
|
2006-01-11 01:17:39 +00:00
|
|
|
pa_mainloop_api *mainloop;
|
2006-07-13 17:33:44 +00:00
|
|
|
AvahiPoll* avahi_poll;
|
2004-12-12 22:58:53 +00:00
|
|
|
|
2006-02-22 20:11:56 +00:00
|
|
|
pa_browse_cb_t callback;
|
|
|
|
|
void *userdata;
|
2004-12-12 22:58:53 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
pa_browser_error_cb_t error_callback;
|
|
|
|
|
void *error_userdata;
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
AvahiClient *client;
|
|
|
|
|
AvahiServiceBrowser *server_browser, *sink_browser, *source_browser;
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
};
|
2006-02-22 20:11:56 +00:00
|
|
|
|
|
|
|
|
static int map_to_opcode(const char *type, int new) {
|
2007-10-28 19:13:50 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
if (avahi_domain_equal(type, SERVICE_TYPE_SINK))
|
2006-02-22 20:11:56 +00:00
|
|
|
return new ? PA_BROWSE_NEW_SINK : PA_BROWSE_REMOVE_SINK;
|
2006-07-13 17:33:44 +00:00
|
|
|
else if (avahi_domain_equal(type, SERVICE_TYPE_SOURCE))
|
2006-02-22 20:11:56 +00:00
|
|
|
return new ? PA_BROWSE_NEW_SOURCE : PA_BROWSE_REMOVE_SOURCE;
|
2006-07-13 17:33:44 +00:00
|
|
|
else if (avahi_domain_equal(type, SERVICE_TYPE_SERVER))
|
2006-02-22 20:11:56 +00:00
|
|
|
return new ? PA_BROWSE_NEW_SERVER : PA_BROWSE_REMOVE_SERVER;
|
|
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
static void resolve_callback(
|
|
|
|
|
AvahiServiceResolver *r,
|
|
|
|
|
AvahiIfIndex interface,
|
|
|
|
|
AvahiProtocol protocol,
|
|
|
|
|
AvahiResolverEvent event,
|
|
|
|
|
const char *name,
|
|
|
|
|
const char *type,
|
|
|
|
|
const char *domain,
|
|
|
|
|
const char *host_name,
|
|
|
|
|
const AvahiAddress *aa,
|
|
|
|
|
uint16_t port,
|
|
|
|
|
AvahiStringList *txt,
|
|
|
|
|
AvahiLookupResultFlags flags,
|
|
|
|
|
void *userdata) {
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
pa_browser *b = userdata;
|
2006-01-11 01:17:39 +00:00
|
|
|
pa_browse_info i;
|
2004-12-12 22:58:53 +00:00
|
|
|
char ip[256], a[256];
|
2006-02-22 20:11:56 +00:00
|
|
|
int opcode;
|
2004-12-12 22:58:53 +00:00
|
|
|
int device_found = 0;
|
|
|
|
|
uint32_t cookie;
|
2006-01-11 01:17:39 +00:00
|
|
|
pa_sample_spec ss;
|
2004-12-12 22:58:53 +00:00
|
|
|
int ss_valid = 0;
|
2006-07-13 17:33:44 +00:00
|
|
|
char *key = NULL, *value = NULL;
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert(b);
|
|
|
|
|
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
2004-12-12 22:58:53 +00:00
|
|
|
|
|
|
|
|
memset(&i, 0, sizeof(i));
|
|
|
|
|
i.name = name;
|
2006-07-13 17:33:44 +00:00
|
|
|
|
|
|
|
|
if (event != AVAHI_RESOLVER_FOUND)
|
|
|
|
|
goto fail;
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2004-12-12 22:58:53 +00:00
|
|
|
if (!b->callback)
|
|
|
|
|
goto fail;
|
|
|
|
|
|
2006-02-22 20:11:56 +00:00
|
|
|
opcode = map_to_opcode(type, 1);
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert(opcode >= 0);
|
2006-07-13 17:33:44 +00:00
|
|
|
|
|
|
|
|
if (aa->proto == AVAHI_PROTO_INET)
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_snprintf(a, sizeof(a), "tcp:%s:%u", avahi_address_snprint(ip, sizeof(ip), aa), port);
|
2006-07-13 17:33:44 +00:00
|
|
|
else {
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert(aa->proto == AVAHI_PROTO_INET6);
|
|
|
|
|
pa_snprintf(a, sizeof(a), "tcp6:%s:%u", avahi_address_snprint(ip, sizeof(ip), aa), port);
|
2006-07-13 17:33:44 +00:00
|
|
|
}
|
2004-12-12 22:58:53 +00:00
|
|
|
i.server = a;
|
|
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
|
|
|
|
|
while (txt) {
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
if (avahi_string_list_get_pair(txt, &key, &value, NULL) < 0)
|
|
|
|
|
break;
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
if (!strcmp(key, "device")) {
|
|
|
|
|
device_found = 1;
|
|
|
|
|
pa_xfree((char*) i.device);
|
|
|
|
|
i.device = value;
|
|
|
|
|
value = NULL;
|
|
|
|
|
} else if (!strcmp(key, "server-version")) {
|
|
|
|
|
pa_xfree((char*) i.server_version);
|
|
|
|
|
i.server_version = value;
|
|
|
|
|
value = NULL;
|
|
|
|
|
} else if (!strcmp(key, "user-name")) {
|
|
|
|
|
pa_xfree((char*) i.user_name);
|
|
|
|
|
i.user_name = value;
|
|
|
|
|
value = NULL;
|
|
|
|
|
} else if (!strcmp(key, "fqdn")) {
|
|
|
|
|
size_t l;
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
pa_xfree((char*) i.fqdn);
|
|
|
|
|
i.fqdn = value;
|
|
|
|
|
value = NULL;
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
l = strlen(a);
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert(l+1 <= sizeof(a));
|
2006-07-13 17:33:44 +00:00
|
|
|
strncat(a, " ", sizeof(a)-l-1);
|
|
|
|
|
strncat(a, i.fqdn, sizeof(a)-l-2);
|
|
|
|
|
} else if (!strcmp(key, "cookie")) {
|
|
|
|
|
|
|
|
|
|
if (pa_atou(value, &cookie) < 0)
|
|
|
|
|
goto fail;
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
i.cookie = &cookie;
|
|
|
|
|
} else if (!strcmp(key, "description")) {
|
|
|
|
|
pa_xfree((char*) i.description);
|
|
|
|
|
i.description = value;
|
|
|
|
|
value = NULL;
|
|
|
|
|
} else if (!strcmp(key, "channels")) {
|
|
|
|
|
uint32_t ch;
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
if (pa_atou(value, &ch) < 0 || ch <= 0 || ch > 255)
|
|
|
|
|
goto fail;
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
ss.channels = (uint8_t) ch;
|
|
|
|
|
ss_valid |= 1;
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
} else if (!strcmp(key, "rate")) {
|
|
|
|
|
if (pa_atou(value, &ss.rate) < 0)
|
|
|
|
|
goto fail;
|
|
|
|
|
ss_valid |= 2;
|
|
|
|
|
} else if (!strcmp(key, "format")) {
|
|
|
|
|
|
|
|
|
|
if ((ss.format = pa_parse_sample_format(value)) == PA_SAMPLE_INVALID)
|
|
|
|
|
goto fail;
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
ss_valid |= 4;
|
|
|
|
|
}
|
2004-12-12 22:58:53 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
pa_xfree(key);
|
|
|
|
|
pa_xfree(value);
|
|
|
|
|
key = value = NULL;
|
2004-12-12 22:58:53 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
txt = avahi_string_list_get_next(txt);
|
2004-12-12 22:58:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* No device txt record was sent for a sink or source service */
|
2007-01-04 13:43:45 +00:00
|
|
|
if (opcode != PA_BROWSE_NEW_SERVER && !device_found)
|
2004-12-12 22:58:53 +00:00
|
|
|
goto fail;
|
|
|
|
|
|
|
|
|
|
if (ss_valid == 7)
|
|
|
|
|
i.sample_spec = &ss;
|
|
|
|
|
|
2006-02-22 20:11:56 +00:00
|
|
|
b->callback(b, opcode, &i, b->userdata);
|
2004-12-12 22:58:53 +00:00
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
pa_xfree(key);
|
|
|
|
|
pa_xfree(value);
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
avahi_service_resolver_free(r);
|
2004-12-12 22:58:53 +00:00
|
|
|
}
|
|
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
static void handle_failure(pa_browser *b) {
|
|
|
|
|
const char *e = NULL;
|
2007-10-28 19:13:50 +00:00
|
|
|
|
|
|
|
|
pa_assert(b);
|
|
|
|
|
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
2004-12-12 22:58:53 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
if (b->sink_browser)
|
|
|
|
|
avahi_service_browser_free(b->sink_browser);
|
|
|
|
|
if (b->source_browser)
|
|
|
|
|
avahi_service_browser_free(b->source_browser);
|
|
|
|
|
if (b->server_browser)
|
|
|
|
|
avahi_service_browser_free(b->server_browser);
|
2004-12-12 22:58:53 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
b->sink_browser = b->source_browser = b->server_browser = NULL;
|
|
|
|
|
|
|
|
|
|
if (b->client) {
|
|
|
|
|
e = avahi_strerror(avahi_client_errno(b->client));
|
|
|
|
|
avahi_client_free(b->client);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
b->client = NULL;
|
|
|
|
|
|
|
|
|
|
if (b->error_callback)
|
|
|
|
|
b->error_callback(b, e, b->error_userdata);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void browse_callback(
|
|
|
|
|
AvahiServiceBrowser *sb,
|
|
|
|
|
AvahiIfIndex interface,
|
|
|
|
|
AvahiProtocol protocol,
|
|
|
|
|
AvahiBrowserEvent event,
|
|
|
|
|
const char *name,
|
|
|
|
|
const char *type,
|
|
|
|
|
const char *domain,
|
|
|
|
|
AvahiLookupResultFlags flags,
|
|
|
|
|
void *userdata) {
|
|
|
|
|
|
|
|
|
|
pa_browser *b = userdata;
|
2007-10-28 19:13:50 +00:00
|
|
|
|
|
|
|
|
pa_assert(b);
|
|
|
|
|
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
2006-07-13 17:33:44 +00:00
|
|
|
|
|
|
|
|
switch (event) {
|
|
|
|
|
case AVAHI_BROWSER_NEW: {
|
|
|
|
|
|
|
|
|
|
if (!avahi_service_resolver_new(
|
|
|
|
|
b->client,
|
|
|
|
|
interface,
|
|
|
|
|
protocol,
|
|
|
|
|
name,
|
|
|
|
|
type,
|
|
|
|
|
domain,
|
|
|
|
|
AVAHI_PROTO_UNSPEC,
|
|
|
|
|
0,
|
|
|
|
|
resolve_callback,
|
|
|
|
|
b))
|
|
|
|
|
handle_failure(b);
|
2004-12-12 22:58:53 +00:00
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
case AVAHI_BROWSER_REMOVE: {
|
|
|
|
|
|
2004-12-12 22:58:53 +00:00
|
|
|
if (b->callback) {
|
2006-01-11 01:17:39 +00:00
|
|
|
pa_browse_info i;
|
2006-02-22 20:11:56 +00:00
|
|
|
int opcode;
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2004-12-12 22:58:53 +00:00
|
|
|
memset(&i, 0, sizeof(i));
|
|
|
|
|
i.name = name;
|
2006-02-22 20:11:56 +00:00
|
|
|
|
|
|
|
|
opcode = map_to_opcode(type, 0);
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert(opcode >= 0);
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2006-02-22 20:11:56 +00:00
|
|
|
b->callback(b, opcode, &i, b->userdata);
|
2004-12-12 22:58:53 +00:00
|
|
|
}
|
|
|
|
|
break;
|
2006-07-13 17:33:44 +00:00
|
|
|
}
|
2004-12-12 22:58:53 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
case AVAHI_BROWSER_FAILURE: {
|
|
|
|
|
handle_failure(b);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2004-12-12 22:58:53 +00:00
|
|
|
default:
|
|
|
|
|
;
|
|
|
|
|
}
|
2006-07-13 17:33:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void client_callback(AvahiClient *s, AvahiClientState state, void *userdata) {
|
|
|
|
|
pa_browser *b = userdata;
|
2007-10-28 19:13:50 +00:00
|
|
|
|
|
|
|
|
pa_assert(s);
|
|
|
|
|
pa_assert(b);
|
|
|
|
|
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
2004-12-12 22:58:53 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
if (state == AVAHI_CLIENT_FAILURE)
|
|
|
|
|
handle_failure(b);
|
2004-12-12 22:58:53 +00:00
|
|
|
}
|
|
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
static void browser_free(pa_browser *b);
|
|
|
|
|
|
2008-05-15 23:34:41 +00:00
|
|
|
|
|
|
|
|
PA_WARN_REFERENCE(pa_browser_new, "libpulse-browse is being phased out.");
|
|
|
|
|
|
2006-01-11 01:17:39 +00:00
|
|
|
pa_browser *pa_browser_new(pa_mainloop_api *mainloop) {
|
2006-07-13 17:33:44 +00:00
|
|
|
return pa_browser_new_full(mainloop, PA_BROWSE_FOR_SERVERS|PA_BROWSE_FOR_SINKS|PA_BROWSE_FOR_SOURCES, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-15 23:34:41 +00:00
|
|
|
PA_WARN_REFERENCE(pa_browser_new_full, "libpulse-browse is being phased out.");
|
|
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
pa_browser *pa_browser_new_full(pa_mainloop_api *mainloop, pa_browse_flags_t flags, const char **error_string) {
|
2006-01-11 01:17:39 +00:00
|
|
|
pa_browser *b;
|
2006-07-13 17:33:44 +00:00
|
|
|
int error;
|
2004-12-12 22:58:53 +00:00
|
|
|
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert(mainloop);
|
2006-07-13 17:33:44 +00:00
|
|
|
|
|
|
|
|
if (flags & ~(PA_BROWSE_FOR_SERVERS|PA_BROWSE_FOR_SINKS|PA_BROWSE_FOR_SOURCES) || flags == 0)
|
|
|
|
|
return NULL;
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2006-02-22 20:11:56 +00:00
|
|
|
b = pa_xnew(pa_browser, 1);
|
2004-12-12 22:58:53 +00:00
|
|
|
b->mainloop = mainloop;
|
2007-10-28 19:13:50 +00:00
|
|
|
PA_REFCNT_INIT(b);
|
2004-12-12 22:58:53 +00:00
|
|
|
b->callback = NULL;
|
2006-02-22 20:11:56 +00:00
|
|
|
b->userdata = NULL;
|
2006-07-13 17:33:44 +00:00
|
|
|
b->error_callback = NULL;
|
|
|
|
|
b->error_userdata = NULL;
|
|
|
|
|
b->sink_browser = b->source_browser = b->server_browser = NULL;
|
2004-12-12 22:58:53 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
b->avahi_poll = pa_avahi_poll_new(mainloop);
|
|
|
|
|
|
|
|
|
|
if (!(b->client = avahi_client_new(b->avahi_poll, 0, client_callback, b, &error))) {
|
|
|
|
|
if (error_string)
|
|
|
|
|
*error_string = avahi_strerror(error);
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((flags & PA_BROWSE_FOR_SERVERS) &&
|
|
|
|
|
!(b->server_browser = avahi_service_browser_new(
|
|
|
|
|
b->client,
|
|
|
|
|
AVAHI_IF_UNSPEC,
|
2007-05-23 23:38:28 +00:00
|
|
|
AVAHI_PROTO_INET,
|
2006-07-13 17:33:44 +00:00
|
|
|
SERVICE_TYPE_SERVER,
|
|
|
|
|
NULL,
|
|
|
|
|
0,
|
|
|
|
|
browse_callback,
|
|
|
|
|
b))) {
|
|
|
|
|
|
|
|
|
|
if (error_string)
|
|
|
|
|
*error_string = avahi_strerror(avahi_client_errno(b->client));
|
|
|
|
|
goto fail;
|
2004-12-12 22:58:53 +00:00
|
|
|
}
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
if ((flags & PA_BROWSE_FOR_SINKS) &&
|
|
|
|
|
!(b->sink_browser = avahi_service_browser_new(
|
|
|
|
|
b->client,
|
|
|
|
|
AVAHI_IF_UNSPEC,
|
|
|
|
|
AVAHI_PROTO_UNSPEC,
|
|
|
|
|
SERVICE_TYPE_SINK,
|
|
|
|
|
NULL,
|
|
|
|
|
0,
|
|
|
|
|
browse_callback,
|
|
|
|
|
b))) {
|
|
|
|
|
|
|
|
|
|
if (error_string)
|
|
|
|
|
*error_string = avahi_strerror(avahi_client_errno(b->client));
|
|
|
|
|
goto fail;
|
|
|
|
|
}
|
2004-12-12 22:58:53 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
if ((flags & PA_BROWSE_FOR_SOURCES) &&
|
|
|
|
|
!(b->source_browser = avahi_service_browser_new(
|
|
|
|
|
b->client,
|
|
|
|
|
AVAHI_IF_UNSPEC,
|
|
|
|
|
AVAHI_PROTO_UNSPEC,
|
|
|
|
|
SERVICE_TYPE_SOURCE,
|
|
|
|
|
NULL,
|
|
|
|
|
0,
|
|
|
|
|
browse_callback,
|
|
|
|
|
b))) {
|
|
|
|
|
|
|
|
|
|
if (error_string)
|
|
|
|
|
*error_string = avahi_strerror(avahi_client_errno(b->client));
|
|
|
|
|
goto fail;
|
2004-12-12 22:58:53 +00:00
|
|
|
}
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2004-12-12 22:58:53 +00:00
|
|
|
return b;
|
2006-07-13 17:33:44 +00:00
|
|
|
|
|
|
|
|
fail:
|
|
|
|
|
if (b)
|
|
|
|
|
browser_free(b);
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
return NULL;
|
2004-12-12 22:58:53 +00:00
|
|
|
}
|
|
|
|
|
|
2006-01-11 01:17:39 +00:00
|
|
|
static void browser_free(pa_browser *b) {
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert(b);
|
|
|
|
|
pa_assert(b->mainloop);
|
2004-12-12 22:58:53 +00:00
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
if (b->sink_browser)
|
|
|
|
|
avahi_service_browser_free(b->sink_browser);
|
|
|
|
|
if (b->source_browser)
|
|
|
|
|
avahi_service_browser_free(b->source_browser);
|
|
|
|
|
if (b->server_browser)
|
|
|
|
|
avahi_service_browser_free(b->server_browser);
|
|
|
|
|
|
|
|
|
|
if (b->client)
|
|
|
|
|
avahi_client_free(b->client);
|
|
|
|
|
|
|
|
|
|
if (b->avahi_poll)
|
|
|
|
|
pa_avahi_poll_free(b->avahi_poll);
|
2007-01-04 13:43:45 +00:00
|
|
|
|
2004-12-12 22:58:53 +00:00
|
|
|
pa_xfree(b);
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-15 23:34:41 +00:00
|
|
|
PA_WARN_REFERENCE(pa_browser_ref, "libpulse-browse is being phased out.");
|
|
|
|
|
|
2006-01-11 01:17:39 +00:00
|
|
|
pa_browser *pa_browser_ref(pa_browser *b) {
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert(b);
|
|
|
|
|
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
|
|
|
|
|
|
|
|
|
PA_REFCNT_INC(b);
|
2004-12-12 22:58:53 +00:00
|
|
|
return b;
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-15 23:34:41 +00:00
|
|
|
PA_WARN_REFERENCE(pa_browser_unref, "libpulse-browse is being phased out.");
|
|
|
|
|
|
2006-01-11 01:17:39 +00:00
|
|
|
void pa_browser_unref(pa_browser *b) {
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert(b);
|
|
|
|
|
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
2004-12-12 22:58:53 +00:00
|
|
|
|
2007-10-28 19:13:50 +00:00
|
|
|
if (PA_REFCNT_DEC(b) <= 0)
|
2004-12-12 22:58:53 +00:00
|
|
|
browser_free(b);
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-15 23:34:41 +00:00
|
|
|
PA_WARN_REFERENCE(pa_browser_set_callback, "libpulse-browse is being phased out.");
|
|
|
|
|
|
2006-02-22 20:11:56 +00:00
|
|
|
void pa_browser_set_callback(pa_browser *b, pa_browse_cb_t cb, void *userdata) {
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert(b);
|
|
|
|
|
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
2004-12-12 22:58:53 +00:00
|
|
|
|
|
|
|
|
b->callback = cb;
|
2006-02-22 20:11:56 +00:00
|
|
|
b->userdata = userdata;
|
2004-12-12 22:58:53 +00:00
|
|
|
}
|
2006-07-13 17:33:44 +00:00
|
|
|
|
2008-05-15 23:34:41 +00:00
|
|
|
PA_WARN_REFERENCE(pa_browser_set_error_callback, "libpulse-browse is being phased out.");
|
|
|
|
|
|
2006-07-13 17:33:44 +00:00
|
|
|
void pa_browser_set_error_callback(pa_browser *b, pa_browser_error_cb_t cb, void *userdata) {
|
2007-10-28 19:13:50 +00:00
|
|
|
pa_assert(b);
|
|
|
|
|
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
2006-07-13 17:33:44 +00:00
|
|
|
|
|
|
|
|
b->error_callback = cb;
|
|
|
|
|
b->error_userdata = userdata;
|
|
|
|
|
}
|