mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
Remove libpulse-browse and pabrowse
This commit is contained in:
parent
909d031134
commit
ebf93404b6
12 changed files with 0 additions and 818 deletions
|
|
@ -46,11 +46,6 @@ vapi_DATA = \
|
||||||
pkgconfigdir = $(libdir)/pkgconfig
|
pkgconfigdir = $(libdir)/pkgconfig
|
||||||
pkgconfig_DATA = libpulse.pc libpulse-simple.pc
|
pkgconfig_DATA = libpulse.pc libpulse-simple.pc
|
||||||
|
|
||||||
if HAVE_AVAHI
|
|
||||||
pkgconfig_DATA += \
|
|
||||||
libpulse-browse.pc
|
|
||||||
endif
|
|
||||||
|
|
||||||
if HAVE_GLIB20
|
if HAVE_GLIB20
|
||||||
pkgconfig_DATA += \
|
pkgconfig_DATA += \
|
||||||
libpulse-mainloop-glib.pc
|
libpulse-mainloop-glib.pc
|
||||||
|
|
|
||||||
|
|
@ -1195,7 +1195,6 @@ src/Makefile
|
||||||
man/Makefile
|
man/Makefile
|
||||||
libpulse.pc
|
libpulse.pc
|
||||||
libpulse-simple.pc
|
libpulse-simple.pc
|
||||||
libpulse-browse.pc
|
|
||||||
libpulse-mainloop-glib.pc
|
libpulse-mainloop-glib.pc
|
||||||
doxygen/Makefile
|
doxygen/Makefile
|
||||||
doxygen/doxygen.conf
|
doxygen/doxygen.conf
|
||||||
|
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
prefix=@prefix@
|
|
||||||
exec_prefix=@exec_prefix@
|
|
||||||
libdir=@libdir@
|
|
||||||
includedir=@includedir@
|
|
||||||
|
|
||||||
Name: libpulse-browse
|
|
||||||
Description: PulseAudio Network Browsing Interface
|
|
||||||
Version: @PACKAGE_VERSION@
|
|
||||||
Libs: -L${libdir} -lpulse-browse @PTHREAD_LIBS@
|
|
||||||
Libs.private: -lpulsecommon-@PA_MAJORMINOR@
|
|
||||||
Cflags: -I${includedir} -D_REENTRANT
|
|
||||||
Requires: libpulse
|
|
||||||
|
|
@ -30,7 +30,6 @@ noinst_DATA = \
|
||||||
pactl.1.xml \
|
pactl.1.xml \
|
||||||
pasuspender.1.xml \
|
pasuspender.1.xml \
|
||||||
padsp.1.xml \
|
padsp.1.xml \
|
||||||
pabrowse.1.xml \
|
|
||||||
pulse-daemon.conf.5.xml \
|
pulse-daemon.conf.5.xml \
|
||||||
pulse-client.conf.5.xml \
|
pulse-client.conf.5.xml \
|
||||||
default.pa.5.xml
|
default.pa.5.xml
|
||||||
|
|
@ -57,7 +56,6 @@ dist_man_MANS = \
|
||||||
pactl.1 \
|
pactl.1 \
|
||||||
pasuspender.1 \
|
pasuspender.1 \
|
||||||
padsp.1 \
|
padsp.1 \
|
||||||
pabrowse.1 \
|
|
||||||
pulse-daemon.conf.5 \
|
pulse-daemon.conf.5 \
|
||||||
pulse-client.conf.5 \
|
pulse-client.conf.5 \
|
||||||
default.pa.5
|
default.pa.5
|
||||||
|
|
@ -80,7 +78,6 @@ EXTRA_DIST = \
|
||||||
pactl.1.xml.in \
|
pactl.1.xml.in \
|
||||||
pasuspender.1.xml.in \
|
pasuspender.1.xml.in \
|
||||||
padsp.1.xml.in \
|
padsp.1.xml.in \
|
||||||
pabrowse.1.xml.in \
|
|
||||||
pulse-daemon.conf.5.xml.in \
|
pulse-daemon.conf.5.xml.in \
|
||||||
pulse-client.conf.5.xml.in \
|
pulse-client.conf.5.xml.in \
|
||||||
default.pa.5.xml.in \
|
default.pa.5.xml.in \
|
||||||
|
|
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
<?xml version="1.0"?><!--*-nxml-*-->
|
|
||||||
<!DOCTYPE manpage SYSTEM "xmltoman.dtd">
|
|
||||||
<?xml-stylesheet type="text/xsl" href="xmltoman.xsl" ?>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
This file is part of PulseAudio.
|
|
||||||
|
|
||||||
PulseAudio is free software; you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU Lesser General Public License as
|
|
||||||
published by the Free Software Foundation; either version 2.1 of the
|
|
||||||
License, or (at your option) any later version.
|
|
||||||
|
|
||||||
PulseAudio is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
|
|
||||||
Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with PulseAudio; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
||||||
USA.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<manpage name="pabrowse" section="1" desc="List PulseAudio sound servers on the network">
|
|
||||||
|
|
||||||
<synopsis>
|
|
||||||
<cmd>pabrowse</cmd>
|
|
||||||
</synopsis>
|
|
||||||
|
|
||||||
<description>
|
|
||||||
<p><file>pabrowse</file> lists all PulseAudio sound servers on the
|
|
||||||
local network that are being announced with Zeroconf/Avahi.</p>
|
|
||||||
|
|
||||||
<p>This program takes no command line arguments.</p>
|
|
||||||
</description>
|
|
||||||
|
|
||||||
<section name="Authors">
|
|
||||||
<p>The PulseAudio Developers <@PACKAGE_BUGREPORT@>; PulseAudio is available from <url href="@PACKAGE_URL@"/></p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section name="See also">
|
|
||||||
<p>
|
|
||||||
<manref name="pulseaudio" section="1"/>, <manref name="avahi-daemon" section="8"/>
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</manpage>
|
|
||||||
|
|
@ -164,7 +164,6 @@ src/pulse/mainloop-api.c
|
||||||
src/pulse/sample.c
|
src/pulse/sample.c
|
||||||
src/pulse/client-conf-x11.c
|
src/pulse/client-conf-x11.c
|
||||||
src/pulse/client-conf.c
|
src/pulse/client-conf.c
|
||||||
src/pulse/browser.c
|
|
||||||
src/pulse/volume.c
|
src/pulse/volume.c
|
||||||
src/pulse/simple.c
|
src/pulse/simple.c
|
||||||
src/pulse/subscribe.c
|
src/pulse/subscribe.c
|
||||||
|
|
@ -180,7 +179,6 @@ src/pulse/timeval.c
|
||||||
src/pulse/format.c
|
src/pulse/format.c
|
||||||
src/utils/pacat.c
|
src/utils/pacat.c
|
||||||
src/utils/pasuspender.c
|
src/utils/pasuspender.c
|
||||||
src/utils/pabrowse.c
|
|
||||||
src/utils/pactl.c
|
src/utils/pactl.c
|
||||||
src/utils/padsp.c
|
src/utils/padsp.c
|
||||||
src/utils/pax11publish.c
|
src/utils/pax11publish.c
|
||||||
|
|
|
||||||
1
src/.gitignore
vendored
1
src/.gitignore
vendored
|
|
@ -37,7 +37,6 @@ mcalign-test
|
||||||
memblock-test
|
memblock-test
|
||||||
memblockq-test
|
memblockq-test
|
||||||
mix-test
|
mix-test
|
||||||
pabrowse
|
|
||||||
pacat
|
pacat
|
||||||
pacat-simple
|
pacat-simple
|
||||||
pacmd
|
pacmd
|
||||||
|
|
|
||||||
|
|
@ -203,10 +203,6 @@ bin_PROGRAMS += pax11publish
|
||||||
bin_SCRIPTS += start-pulseaudio-x11 start-pulseaudio-kde
|
bin_SCRIPTS += start-pulseaudio-x11 start-pulseaudio-kde
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if HAVE_AVAHI
|
|
||||||
bin_PROGRAMS += pabrowse
|
|
||||||
endif
|
|
||||||
|
|
||||||
pacat_SOURCES = utils/pacat.c
|
pacat_SOURCES = utils/pacat.c
|
||||||
pacat_LDADD = $(AM_LDADD) libpulse.la libpulsecommon-@PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS)
|
pacat_LDADD = $(AM_LDADD) libpulse.la libpulsecommon-@PA_MAJORMINOR@.la $(LIBSNDFILE_LIBS)
|
||||||
pacat_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS)
|
pacat_CFLAGS = $(AM_CFLAGS) $(LIBSNDFILE_CFLAGS)
|
||||||
|
|
@ -232,11 +228,6 @@ pax11publish_CFLAGS = $(AM_CFLAGS) $(X11_CFLAGS)
|
||||||
pax11publish_LDADD = $(AM_LDADD) libpulse.la libpulsecommon-@PA_MAJORMINOR@.la $(X11_LIBS)
|
pax11publish_LDADD = $(AM_LDADD) libpulse.la libpulsecommon-@PA_MAJORMINOR@.la $(X11_LIBS)
|
||||||
pax11publish_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
pax11publish_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
||||||
|
|
||||||
pabrowse_SOURCES = utils/pabrowse.c
|
|
||||||
pabrowse_LDADD = $(AM_LDADD) libpulse.la libpulse-browse.la libpulsecommon-@PA_MAJORMINOR@.la
|
|
||||||
pabrowse_CFLAGS = $(AM_CFLAGS)
|
|
||||||
pabrowse_LDFLAGS = $(AM_LDFLAGS) $(BINLDFLAGS)
|
|
||||||
|
|
||||||
###################################
|
###################################
|
||||||
# Test programs #
|
# Test programs #
|
||||||
###################################
|
###################################
|
||||||
|
|
@ -716,14 +707,6 @@ lib_LTLIBRARIES += \
|
||||||
libpulse.la \
|
libpulse.la \
|
||||||
libpulse-simple.la
|
libpulse-simple.la
|
||||||
|
|
||||||
if HAVE_AVAHI
|
|
||||||
pulseinclude_HEADERS += \
|
|
||||||
pulse/browser.h
|
|
||||||
|
|
||||||
lib_LTLIBRARIES += \
|
|
||||||
libpulse-browse.la
|
|
||||||
endif
|
|
||||||
|
|
||||||
if HAVE_GLIB20
|
if HAVE_GLIB20
|
||||||
pulseinclude_HEADERS += \
|
pulseinclude_HEADERS += \
|
||||||
pulse/glib-mainloop.h
|
pulse/glib-mainloop.h
|
||||||
|
|
@ -777,11 +760,6 @@ libpulse_simple_la_CFLAGS = $(AM_CFLAGS)
|
||||||
libpulse_simple_la_LIBADD = $(AM_LIBADD) libpulse.la libpulsecommon-@PA_MAJORMINOR@.la
|
libpulse_simple_la_LIBADD = $(AM_LIBADD) libpulse.la libpulsecommon-@PA_MAJORMINOR@.la
|
||||||
libpulse_simple_la_LDFLAGS = $(AM_LDFLAGS) $(VERSIONING_LDFLAGS) -version-info $(LIBPULSE_SIMPLE_VERSION_INFO)
|
libpulse_simple_la_LDFLAGS = $(AM_LDFLAGS) $(VERSIONING_LDFLAGS) -version-info $(LIBPULSE_SIMPLE_VERSION_INFO)
|
||||||
|
|
||||||
libpulse_browse_la_SOURCES = pulse/browser.c pulse/browser.h pulsecore/avahi-wrap.c pulsecore/avahi-wrap.h
|
|
||||||
libpulse_browse_la_CFLAGS = $(AM_CFLAGS) $(AVAHI_CFLAGS)
|
|
||||||
libpulse_browse_la_LIBADD = $(AM_LIBADD) libpulse.la libpulsecommon-@PA_MAJORMINOR@.la $(AVAHI_LIBS)
|
|
||||||
libpulse_browse_la_LDFLAGS = $(AM_LDFLAGS) $(VERSIONING_LDFLAGS) -version-info $(LIBPULSE_BROWSE_VERSION_INFO)
|
|
||||||
|
|
||||||
libpulse_mainloop_glib_la_SOURCES = pulse/glib-mainloop.h pulse/glib-mainloop.c
|
libpulse_mainloop_glib_la_SOURCES = pulse/glib-mainloop.h pulse/glib-mainloop.c
|
||||||
libpulse_mainloop_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS)
|
libpulse_mainloop_glib_la_CFLAGS = $(AM_CFLAGS) $(GLIB20_CFLAGS)
|
||||||
libpulse_mainloop_glib_la_LIBADD = $(AM_LIBADD) libpulse.la libpulsecommon-@PA_MAJORMINOR@.la $(GLIB20_LIBS)
|
libpulse_mainloop_glib_la_LIBADD = $(AM_LIBADD) libpulse.la libpulsecommon-@PA_MAJORMINOR@.la $(GLIB20_LIBS)
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,6 @@ PULSE_0 {
|
||||||
global:
|
global:
|
||||||
pa_ascii_filter;
|
pa_ascii_filter;
|
||||||
pa_ascii_valid;
|
pa_ascii_valid;
|
||||||
pa_browser_new;
|
|
||||||
pa_browser_new_full;
|
|
||||||
pa_browser_ref;
|
|
||||||
pa_browser_set_callback;
|
|
||||||
pa_browser_set_error_callback;
|
|
||||||
pa_browser_unref;
|
|
||||||
pa_bytes_per_second;
|
pa_bytes_per_second;
|
||||||
pa_bytes_snprint;
|
pa_bytes_snprint;
|
||||||
pa_bytes_to_usec;
|
pa_bytes_to_usec;
|
||||||
|
|
|
||||||
|
|
@ -1,464 +0,0 @@
|
||||||
/***
|
|
||||||
This file is part of PulseAudio.
|
|
||||||
|
|
||||||
Copyright 2004-2006 Lennart Poettering
|
|
||||||
|
|
||||||
PulseAudio is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as
|
|
||||||
published by the Free Software Foundation; either version 2.1 of the
|
|
||||||
License, or (at your option) any later version.
|
|
||||||
|
|
||||||
PulseAudio is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with PulseAudio; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
||||||
USA.
|
|
||||||
***/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <avahi-client/lookup.h>
|
|
||||||
#include <avahi-common/domain.h>
|
|
||||||
#include <avahi-common/error.h>
|
|
||||||
|
|
||||||
#include <pulse/xmalloc.h>
|
|
||||||
|
|
||||||
#include <pulsecore/log.h>
|
|
||||||
#include <pulsecore/core-util.h>
|
|
||||||
#include <pulsecore/avahi-wrap.h>
|
|
||||||
#include <pulsecore/refcnt.h>
|
|
||||||
#include <pulsecore/macro.h>
|
|
||||||
|
|
||||||
#include "browser.h"
|
|
||||||
|
|
||||||
#define SERVICE_TYPE_SINK "_pulse-sink._tcp."
|
|
||||||
#define SERVICE_TYPE_SOURCE "_pulse-source._tcp."
|
|
||||||
#define SERVICE_TYPE_SERVER "_pulse-server._tcp."
|
|
||||||
|
|
||||||
struct pa_browser {
|
|
||||||
PA_REFCNT_DECLARE;
|
|
||||||
|
|
||||||
pa_mainloop_api *mainloop;
|
|
||||||
AvahiPoll* avahi_poll;
|
|
||||||
|
|
||||||
pa_browse_cb_t callback;
|
|
||||||
void *userdata;
|
|
||||||
|
|
||||||
pa_browser_error_cb_t error_callback;
|
|
||||||
void *error_userdata;
|
|
||||||
|
|
||||||
AvahiClient *client;
|
|
||||||
AvahiServiceBrowser *server_browser, *sink_browser, *source_browser;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
static int map_to_opcode(const char *type, int new) {
|
|
||||||
|
|
||||||
if (avahi_domain_equal(type, SERVICE_TYPE_SINK))
|
|
||||||
return new ? PA_BROWSE_NEW_SINK : PA_BROWSE_REMOVE_SINK;
|
|
||||||
else if (avahi_domain_equal(type, SERVICE_TYPE_SOURCE))
|
|
||||||
return new ? PA_BROWSE_NEW_SOURCE : PA_BROWSE_REMOVE_SOURCE;
|
|
||||||
else if (avahi_domain_equal(type, SERVICE_TYPE_SERVER))
|
|
||||||
return new ? PA_BROWSE_NEW_SERVER : PA_BROWSE_REMOVE_SERVER;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
|
|
||||||
pa_browser *b = userdata;
|
|
||||||
pa_browse_info i;
|
|
||||||
char ip[256], a[256];
|
|
||||||
int opcode;
|
|
||||||
int device_found = 0;
|
|
||||||
uint32_t cookie;
|
|
||||||
pa_sample_spec ss;
|
|
||||||
int ss_valid = 0;
|
|
||||||
char *key = NULL, *value = NULL;
|
|
||||||
|
|
||||||
pa_assert(b);
|
|
||||||
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
|
||||||
|
|
||||||
memset(&i, 0, sizeof(i));
|
|
||||||
i.name = name;
|
|
||||||
|
|
||||||
if (event != AVAHI_RESOLVER_FOUND)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
if (!b->callback)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
opcode = map_to_opcode(type, 1);
|
|
||||||
pa_assert(opcode >= 0);
|
|
||||||
|
|
||||||
if (aa->proto == AVAHI_PROTO_INET)
|
|
||||||
pa_snprintf(a, sizeof(a), "tcp:%s:%u", avahi_address_snprint(ip, sizeof(ip), aa), port);
|
|
||||||
else {
|
|
||||||
pa_assert(aa->proto == AVAHI_PROTO_INET6);
|
|
||||||
pa_snprintf(a, sizeof(a), "tcp6:%s:%u", avahi_address_snprint(ip, sizeof(ip), aa), port);
|
|
||||||
}
|
|
||||||
i.server = a;
|
|
||||||
|
|
||||||
|
|
||||||
while (txt) {
|
|
||||||
|
|
||||||
if (avahi_string_list_get_pair(txt, &key, &value, NULL) < 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (!strcmp(key, "device")) {
|
|
||||||
device_found = 1;
|
|
||||||
pa_xfree((char*) i.device);
|
|
||||||
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;
|
|
||||||
|
|
||||||
pa_xfree((char*) i.fqdn);
|
|
||||||
i.fqdn = value;
|
|
||||||
value = NULL;
|
|
||||||
|
|
||||||
l = strlen(a);
|
|
||||||
pa_assert(l+1 <= sizeof(a));
|
|
||||||
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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (pa_atou(value, &ch) < 0 || ch <= 0 || ch > 255)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
ss.channels = (uint8_t) ch;
|
|
||||||
ss_valid |= 1;
|
|
||||||
|
|
||||||
} else if (!strcmp(key, "rate")) {
|
|
||||||
if (pa_atou(value, &ss.rate) < 0)
|
|
||||||
goto fail;
|
|
||||||
ss_valid |= 2;
|
|
||||||
} else if (!strcmp(key, "format")) {
|
|
||||||
|
|
||||||
if ((ss.format = pa_parse_sample_format(value)) == PA_SAMPLE_INVALID)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
ss_valid |= 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
pa_xfree(key);
|
|
||||||
pa_xfree(value);
|
|
||||||
key = value = NULL;
|
|
||||||
|
|
||||||
txt = avahi_string_list_get_next(txt);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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->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(key);
|
|
||||||
pa_xfree(value);
|
|
||||||
|
|
||||||
avahi_service_resolver_free(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void handle_failure(pa_browser *b) {
|
|
||||||
const char *e = NULL;
|
|
||||||
|
|
||||||
pa_assert(b);
|
|
||||||
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
pa_assert(b);
|
|
||||||
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AVAHI_BROWSER_REMOVE: {
|
|
||||||
|
|
||||||
if (b->callback) {
|
|
||||||
pa_browse_info i;
|
|
||||||
int opcode;
|
|
||||||
|
|
||||||
memset(&i, 0, sizeof(i));
|
|
||||||
i.name = name;
|
|
||||||
|
|
||||||
opcode = map_to_opcode(type, 0);
|
|
||||||
pa_assert(opcode >= 0);
|
|
||||||
|
|
||||||
b->callback(b, opcode, &i, b->userdata);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case AVAHI_BROWSER_FAILURE: {
|
|
||||||
handle_failure(b);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void client_callback(AvahiClient *s, AvahiClientState state, void *userdata) {
|
|
||||||
pa_browser *b = userdata;
|
|
||||||
|
|
||||||
pa_assert(s);
|
|
||||||
pa_assert(b);
|
|
||||||
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
|
||||||
|
|
||||||
if (state == AVAHI_CLIENT_FAILURE)
|
|
||||||
handle_failure(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void browser_free(pa_browser *b);
|
|
||||||
|
|
||||||
|
|
||||||
PA_WARN_REFERENCE(pa_browser_new, "libpulse-browse is being phased out.");
|
|
||||||
|
|
||||||
pa_browser *pa_browser_new(pa_mainloop_api *mainloop) {
|
|
||||||
return pa_browser_new_full(mainloop, PA_BROWSE_FOR_SERVERS|PA_BROWSE_FOR_SINKS|PA_BROWSE_FOR_SOURCES, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
PA_WARN_REFERENCE(pa_browser_new_full, "libpulse-browse is being phased out.");
|
|
||||||
|
|
||||||
pa_browser *pa_browser_new_full(pa_mainloop_api *mainloop, pa_browse_flags_t flags, const char **error_string) {
|
|
||||||
pa_browser *b;
|
|
||||||
int error;
|
|
||||||
|
|
||||||
pa_assert(mainloop);
|
|
||||||
|
|
||||||
if (flags & ~(PA_BROWSE_FOR_SERVERS|PA_BROWSE_FOR_SINKS|PA_BROWSE_FOR_SOURCES) || flags == 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
b = pa_xnew(pa_browser, 1);
|
|
||||||
b->mainloop = mainloop;
|
|
||||||
PA_REFCNT_INIT(b);
|
|
||||||
b->callback = NULL;
|
|
||||||
b->userdata = NULL;
|
|
||||||
b->error_callback = NULL;
|
|
||||||
b->error_userdata = NULL;
|
|
||||||
b->sink_browser = b->source_browser = b->server_browser = NULL;
|
|
||||||
|
|
||||||
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,
|
|
||||||
AVAHI_PROTO_INET,
|
|
||||||
SERVICE_TYPE_SERVER,
|
|
||||||
NULL,
|
|
||||||
0,
|
|
||||||
browse_callback,
|
|
||||||
b))) {
|
|
||||||
|
|
||||||
if (error_string)
|
|
||||||
*error_string = avahi_strerror(avahi_client_errno(b->client));
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((flags & PA_BROWSE_FOR_SINKS) &&
|
|
||||||
!(b->sink_browser = avahi_service_browser_new(
|
|
||||||
b->client,
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return b;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
if (b)
|
|
||||||
browser_free(b);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void browser_free(pa_browser *b) {
|
|
||||||
pa_assert(b);
|
|
||||||
pa_assert(b->mainloop);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
pa_xfree(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
PA_WARN_REFERENCE(pa_browser_ref, "libpulse-browse is being phased out.");
|
|
||||||
|
|
||||||
pa_browser *pa_browser_ref(pa_browser *b) {
|
|
||||||
pa_assert(b);
|
|
||||||
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
|
||||||
|
|
||||||
PA_REFCNT_INC(b);
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
PA_WARN_REFERENCE(pa_browser_unref, "libpulse-browse is being phased out.");
|
|
||||||
|
|
||||||
void pa_browser_unref(pa_browser *b) {
|
|
||||||
pa_assert(b);
|
|
||||||
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
|
||||||
|
|
||||||
if (PA_REFCNT_DEC(b) <= 0)
|
|
||||||
browser_free(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
PA_WARN_REFERENCE(pa_browser_set_callback, "libpulse-browse is being phased out.");
|
|
||||||
|
|
||||||
void pa_browser_set_callback(pa_browser *b, pa_browse_cb_t cb, void *userdata) {
|
|
||||||
pa_assert(b);
|
|
||||||
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
|
||||||
|
|
||||||
b->callback = cb;
|
|
||||||
b->userdata = userdata;
|
|
||||||
}
|
|
||||||
|
|
||||||
PA_WARN_REFERENCE(pa_browser_set_error_callback, "libpulse-browse is being phased out.");
|
|
||||||
|
|
||||||
void pa_browser_set_error_callback(pa_browser *b, pa_browser_error_cb_t cb, void *userdata) {
|
|
||||||
pa_assert(b);
|
|
||||||
pa_assert(PA_REFCNT_VALUE(b) >= 1);
|
|
||||||
|
|
||||||
b->error_callback = cb;
|
|
||||||
b->error_userdata = userdata;
|
|
||||||
}
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
#ifndef foobrowserhfoo
|
|
||||||
#define foobrowserhfoo
|
|
||||||
|
|
||||||
/***
|
|
||||||
This file is part of PulseAudio.
|
|
||||||
|
|
||||||
Copyright 2004-2006 Lennart Poettering
|
|
||||||
|
|
||||||
PulseAudio is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as
|
|
||||||
published by the Free Software Foundation; either version 2.1 of the
|
|
||||||
License, or (at your option) any later version.
|
|
||||||
|
|
||||||
PulseAudio is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
|
||||||
License along with PulseAudio; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
||||||
USA.
|
|
||||||
***/
|
|
||||||
|
|
||||||
#include <pulse/mainloop-api.h>
|
|
||||||
#include <pulse/sample.h>
|
|
||||||
#include <pulse/channelmap.h>
|
|
||||||
#include <pulse/cdecl.h>
|
|
||||||
#include <pulse/version.h>
|
|
||||||
|
|
||||||
/** \file
|
|
||||||
* An abstract interface for Zeroconf browsing of PulseAudio servers */
|
|
||||||
|
|
||||||
PA_C_DECL_BEGIN
|
|
||||||
|
|
||||||
/** An opaque Zeroconf service browser object */
|
|
||||||
typedef struct pa_browser pa_browser;
|
|
||||||
|
|
||||||
/** Opcodes for pa_browser_cb_t callbacks */
|
|
||||||
typedef enum pa_browse_opcode {
|
|
||||||
PA_BROWSE_NEW_SERVER = 0, /**< New server found */
|
|
||||||
PA_BROWSE_NEW_SINK, /**< New sink found */
|
|
||||||
PA_BROWSE_NEW_SOURCE, /**< New source found */
|
|
||||||
PA_BROWSE_REMOVE_SERVER, /**< Server disappeared */
|
|
||||||
PA_BROWSE_REMOVE_SINK, /**< Sink disappeared */
|
|
||||||
PA_BROWSE_REMOVE_SOURCE /**< Source disappeared */
|
|
||||||
} pa_browse_opcode_t;
|
|
||||||
|
|
||||||
typedef enum pa_browse_flags {
|
|
||||||
PA_BROWSE_FOR_SERVERS = 1, /**< Browse for servers */
|
|
||||||
PA_BROWSE_FOR_SINKS = 2, /**< Browse for sinks */
|
|
||||||
PA_BROWSE_FOR_SOURCES = 4 /** Browse for sources */
|
|
||||||
} pa_browse_flags_t;
|
|
||||||
|
|
||||||
/** Create a new browser object on the specified main loop */
|
|
||||||
pa_browser *pa_browser_new(pa_mainloop_api *mainloop);
|
|
||||||
|
|
||||||
/** Same pa_browser_new, but pass additional flags parameter. */
|
|
||||||
pa_browser *pa_browser_new_full(pa_mainloop_api *mainloop, pa_browse_flags_t flags, const char **error_string);
|
|
||||||
|
|
||||||
/** Increase reference counter of the specified browser object */
|
|
||||||
pa_browser *pa_browser_ref(pa_browser *z);
|
|
||||||
|
|
||||||
/** Decrease reference counter of the specified browser object */
|
|
||||||
void pa_browser_unref(pa_browser *z);
|
|
||||||
|
|
||||||
/** Information about a sink/source/server found with Zeroconf */
|
|
||||||
typedef struct pa_browse_info {
|
|
||||||
const char *name; /**< Unique service name; always available */
|
|
||||||
|
|
||||||
const char *server; /**< Server name; always available */
|
|
||||||
const char *server_version; /**< Server version string; optional */
|
|
||||||
const char *user_name; /**< User name of the server process; optional */
|
|
||||||
const char *fqdn; /* Server version; optional */
|
|
||||||
const uint32_t *cookie; /* Server cookie; optional */
|
|
||||||
|
|
||||||
const char *device; /* Device name; always available when this information is of a sink/source */
|
|
||||||
const char *description; /* Device description; optional */
|
|
||||||
const pa_sample_spec *sample_spec; /* Sample specification of the device; optional */
|
|
||||||
} pa_browse_info;
|
|
||||||
|
|
||||||
/** Callback prototype */
|
|
||||||
typedef void (*pa_browse_cb_t)(pa_browser *z, pa_browse_opcode_t c, const pa_browse_info *i, void *userdata);
|
|
||||||
|
|
||||||
/** Set the callback pointer for the browser object */
|
|
||||||
void pa_browser_set_callback(pa_browser *z, pa_browse_cb_t cb, void *userdata);
|
|
||||||
|
|
||||||
/** Callback prototype for errors */
|
|
||||||
typedef void (*pa_browser_error_cb_t)(pa_browser *z, const char *error_string, void *userdata);
|
|
||||||
|
|
||||||
/** Set a callback function that is called whenever the browser object
|
|
||||||
* becomes invalid due to an error. After this function has been
|
|
||||||
* called the browser object has become invalid and should be
|
|
||||||
* freed. */
|
|
||||||
void pa_browser_set_error_callback(pa_browser *z, pa_browser_error_cb_t, void *userdata);
|
|
||||||
|
|
||||||
PA_C_DECL_END
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,156 +0,0 @@
|
||||||
/***
|
|
||||||
This file is part of PulseAudio.
|
|
||||||
|
|
||||||
Copyright 2004-2006 Lennart Poettering
|
|
||||||
|
|
||||||
PulseAudio is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Lesser General Public License as published
|
|
||||||
by the Free Software Foundation; either version 2.1 of the License,
|
|
||||||
or (at your option) any later version.
|
|
||||||
|
|
||||||
PulseAudio is distributed in the hope that it will be useful, but
|
|
||||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public License
|
|
||||||
along with PulseAudio; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
|
||||||
USA.
|
|
||||||
***/
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include <config.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
#include <pulse/browser.h>
|
|
||||||
#include <pulse/pulseaudio.h>
|
|
||||||
|
|
||||||
#include <pulsecore/core-util.h>
|
|
||||||
|
|
||||||
static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) {
|
|
||||||
fprintf(stderr, "Got signal, exiting\n");
|
|
||||||
m->quit(m, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dump_server(const 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 pa_browse_info *i) {
|
|
||||||
char ss[PA_SAMPLE_SPEC_SNPRINT_MAX];
|
|
||||||
|
|
||||||
if (i->sample_spec)
|
|
||||||
pa_sample_spec_snprint(ss, sizeof(ss), i->sample_spec);
|
|
||||||
|
|
||||||
printf("device: %s\n"
|
|
||||||
"description: %s\n"
|
|
||||||
"sample spec: %s\n",
|
|
||||||
i->device,
|
|
||||||
i->description ? i->description : "n/a",
|
|
||||||
i->sample_spec ? ss : "n/a");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static void browser_callback(pa_browser *b, pa_browse_opcode_t c, const pa_browse_info *i, void *userdata) {
|
|
||||||
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_SERVER:
|
|
||||||
printf("\n=> removed server <%s>\n", i->name);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PA_BROWSE_REMOVE_SINK:
|
|
||||||
printf("\n=> removed sink <%s>\n", i->name);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PA_BROWSE_REMOVE_SOURCE:
|
|
||||||
printf("\n=> removed source <%s>\n", i->name);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void error_callback(pa_browser *b, const char *s, void *userdata) {
|
|
||||||
pa_mainloop_api*m = userdata;
|
|
||||||
|
|
||||||
fprintf(stderr, "Failure: %s\n", s);
|
|
||||||
m->quit(m, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
pa_mainloop *mainloop = NULL;
|
|
||||||
pa_browser *browser = NULL;
|
|
||||||
int ret = 1, r;
|
|
||||||
const char *s;
|
|
||||||
|
|
||||||
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);
|
|
||||||
pa_disable_sigpipe();
|
|
||||||
|
|
||||||
if (!(browser = pa_browser_new_full(pa_mainloop_get_api(mainloop), PA_BROWSE_FOR_SERVERS|PA_BROWSE_FOR_SINKS|PA_BROWSE_FOR_SOURCES, &s))) {
|
|
||||||
fprintf(stderr, "pa_browse_new_full(): %s\n", s);
|
|
||||||
goto finish;
|
|
||||||
}
|
|
||||||
|
|
||||||
pa_browser_set_callback(browser, browser_callback, NULL);
|
|
||||||
pa_browser_set_error_callback(browser, error_callback, pa_mainloop_get_api(mainloop));
|
|
||||||
|
|
||||||
ret = 0;
|
|
||||||
pa_mainloop_run(mainloop, &ret);
|
|
||||||
|
|
||||||
finish:
|
|
||||||
|
|
||||||
if (browser)
|
|
||||||
pa_browser_unref(browser);
|
|
||||||
|
|
||||||
if (mainloop) {
|
|
||||||
pa_signal_done();
|
|
||||||
pa_mainloop_free(mainloop);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue