ACLOCAL_AMFLAGS = -I m4
pulsemodlibexecdir= $(libdir)/pulse-5.0/modules
+pulselibexecdir=$(libexecdir)/pulse
AM_CFLAGS = \
$(PTHREAD_CFLAGS)
pulsemodlibexec_LTLIBRARIES = \
libhal-interface.la \
+ libcommunicator.la \
module-tizenaudio-sink.la \
module-tizenaudio-source.la \
module-tizenaudio-policy.la \
# These are generated by an M4 script
SYMDEF_FILES = \
libhal-interface-symdef.h \
+ libcommunicator-symdef.h \
module-tizenaudio-sink-symdef.h \
module-tizenaudio-source-symdef.h \
module-tizenaudio-policy-symdef.h \
module-tizenaudio-haltc-symdef.h
endif
+if ENABLE_VCONF_HELPER
+SYMDEF_FILES += \
+ module-vconf-symdef.h
+endif
+
if HAVE_DBUS
endif
libhal_interface_la_LIBADD = $(AM_LIBADD) $(PACORE_LIBS) $(PA_LIBS)
libhal_interface_la_CFLAGS = $(AM_CFLAGS) $(PACORE_CFLAGS) $(PA_CFLAGS)
+libcommunicator_la_SOURCES = \
+ src/communicator.c src/communicator.h
+libcommunicator_la_LDFLAGS = $(AM_LDFLAGS) $(PA_LDFLAGS) -avoid-version
+libcommunicator_la_LIBADD = $(AM_LIBADD) $(PACORE_LIBS) $(PA_LIBS)
+libcommunicator_la_CFLAGS = $(AM_CFLAGS) $(PACORE_CFLAGS) $(PA_CFLAGS)
+
module_tizenaudio_sink_la_SOURCES = src/module-tizenaudio-sink.c
module_tizenaudio_sink_la_LDFLAGS = $(MODULE_LDFLAGS)
module_tizenaudio_sink_la_LIBADD = $(MODULE_LIBADD) libhal-interface.la
module_tizenaudio_policy_la_SOURCES = \
src/module-tizenaudio-policy.c \
- src/communicator.c src/communicator.h \
src/stream-manager.c src/stream-manager.h src/stream-manager-priv.h \
src/stream-manager-volume.c src/stream-manager-volume.h src/stream-manager-volume-priv.h \
src/stream-manager-restriction.c src/stream-manager-restriction-priv.h \
src/device-manager.c src/device-manager.h src/tizen-device.c src/tizen-device.h src/tizen-device-def.c src/tizen-device-def.h \
src/subscribe-observer.c src/subscribe-observer.h
module_tizenaudio_policy_la_LDFLAGS = $(MODULE_LDFLAGS) -L$(pulsemodlibexecdir)
-module_tizenaudio_policy_la_LIBADD = $(MODULE_LIBADD) $(DBUS_LIBS) $(VCONF_LIBS) $(INIPARSER_LIBS) $(LIBJSON_LIBS) libhal-interface.la
+module_tizenaudio_policy_la_LIBADD = $(MODULE_LIBADD) $(DBUS_LIBS) $(VCONF_LIBS) $(INIPARSER_LIBS) $(LIBJSON_LIBS) libhal-interface.la libcommunicator.la
module_tizenaudio_policy_la_CFLAGS = $(MODULE_CFLAGS) $(DBUS_CFLAGS) $(VCONF_CFLAGS) $(INIPARSER_CFLAGS) $(LIBJSON_CFLAGS)
if ENABLE_HALTC
module_hw_keysound_la_LDFLAGS = $(MODULE_LDFLAGS)
module_hw_keysound_la_LIBADD = $(MODULE_LIBADD) $(DBUS_LIBS) $(VCONF_LIBS)
module_hw_keysound_la_CFLAGS = $(MODULE_CFLAGS) $(DBUS_CFLAGS) $(VCONF_CFLAGS)
+
+if ENABLE_VCONF_HELPER
+pulsemodlibexec_LTLIBRARIES += module-vconf.la
+
+module_vconf_la_SOURCES = src/vconf/module-vconf.c
+module_vconf_la_LDFLAGS = $(MODULE_LDFLAGS)
+module_vconf_la_LIBADD = $(MODULE_LIBADD) libcommunicator.la
+module_vconf_la_CFLAGS = $(MODULE_CFLAGS) -DPA_VCONF_HELPER=\"$(pulselibexecdir)/vconf-helper\"
+
+pulselibexec_PROGRAMS = vconf-helper
+
+vconf_helper_SOURCES = src/vconf/vconf-helper.c
+vconf_helper_LDFLAGS = $(AM_LDFLAGS)
+vconf_helper_LDADD = $(AM_LIBADD) $(GLIB2_LIBS) $(VCONF_LIBS)
+vconf_helper_CFLAGS = $(AM_CFLAGS) $(GLIB2_CFLAGS) $(VCONF_CFLAGS) -fPIC -pie
+endif
PKG_CHECK_MODULES(PA, libpulse)
AC_SUBST(PA_CFLAGS)
AC_SUBST(PA_LIBS)
+AC_SUBST(PA_LDFLAGS)
PKG_CHECK_MODULES(PACORE, pulsecore)
AC_SUBST(PACORE_CFLAGS)
AX_DEFINE_DIR(PA_MACHINE_ID_FALLBACK, PA_MACHINE_ID_FALLBACK,
[Fallback machine-id file])
+#### vconf helper support (optional) ####
+PKG_CHECK_MODULES(GLIB2, glib-2.0)
+AC_SUBST(GLIB2_CFLAGS)
+AC_SUBST(GLIB2_LIBS)
+
+AC_ARG_ENABLE(vconf-helper, AC_HELP_STRING([--enable-vconf-helper], [using vconf-helper]),
+[
+ case "${enableval}" in
+ yes) ENABLE_VCONF_HELPER=yes ;;
+ no) ENABLE_VCONF_HELPER=no ;;
+ *) AC_MSG_ERROR(bad value ${enableval} for --enable-vconf-helper) ;;
+ esac
+ ],[ENABLE_VCONF_HELPER=no])
+AM_CONDITIONAL(ENABLE_VCONF_HELPER, test "x$ENABLE_VCONF_HELPER" = "xyes")
+
###################################
# Output #
###################################
Name: pulseaudio-modules-tizen
Summary: Pulseaudio modules for Tizen
-Version: 5.0.88
+Version: 5.0.89
Release: 0
Group: Multimedia/Audio
License: LGPL-2.1+
BuildRequires: pkgconfig(iniparser)
BuildRequires: pkgconfig(json-c)
BuildRequires: pkgconfig(vconf)
+%if "%{?TIZEN_PRODUCT_TV}" == "1"
+BuildRequires: pkgconfig(glib-2.0)
+%endif
BuildRequires: mm-hal-interface
BuildRequires: pkgconfig(libpulse)
BuildRequires: pkgconfig(pulsecore)
export LD_AS_NEEDED=0
%reconfigure --prefix=%{_prefix} \
--disable-static \
+%if "%{?TIZEN_PRODUCT_TV}" == "1"
+ --enable-vconf-helper
+%endif
# --enable-haltc
%__make %{?_smp_mflags} V=1
%license LICENSE.LGPL-2.1+
%{_libdir}/pulse-5.0/modules/module-*.so
%{_libdir}/pulse-5.0/modules/libhal-interface.so
+%{_libdir}/pulse-5.0/modules/libcommunicator.so
%{_tmpfilesdir}/pulseaudio.conf
+%if "%{?TIZEN_PRODUCT_TV}" == "1"
+%{_libdir}/pulse-5.0/modules/module-vconf.so
+%{_libexecdir}/pulse/vconf-helper
+%endif
PA_COMMUNICATOR_HOOK_DEVICE_STATE_CHANGED, /* It is fired when a device's state is changed */
PA_COMMUNICATOR_HOOK_EVENT_FULLY_HANDLED, /* It is fired when a event is handled by all subscribers */
PA_COMMUNICATOR_HOOK_UPDATE_INFORMATION, /* It is fired when information should be updated */
+ PA_COMMUNICATOR_HOOK_UPDATE_VCONF, /* It is fired when a vconf has updated */
PA_COMMUNICATOR_HOOK_MAX
} pa_communicator_hook_t;
--- /dev/null
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2016 KimJeongYeon <jeongyeon.kim@samsung.com>
+
+ 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.
+***/
+
+#ifndef footizenmodulevconffoo
+#define footizenmodulevconffoo
+
+/* Definition for hooking method */
+typedef struct _hook_call_data_for_vconf_changed {
+ char *key;
+ char *value;
+} pa_module_vconf_hook_data_for_vconf_changed;
+
+/* Definitions for vconf prefix items */
+enum {
+ VCONF_PATH_PREFIX_VOLUME = 0,
+ /* TODO: TBD */
+ VCONF_PATH_PREFIX_MAX
+};
+
+const char *vconf_prefix[VCONF_PATH_PREFIX_MAX] = {
+ "file/private/sound/volume/", /**< VCONF_PATH_PREFIX_VOLUME */
+ /* TODO: TBD */
+};
+
+/* Definitions for vconf items for watching */
+struct vconf_item {
+ char opcode;
+ int prefix;
+ const char *name;
+ int is_notify;
+} vitems[] = {
+ { 'V', VCONF_PATH_PREFIX_VOLUME, "AD", 0 },
+ { 'V', VCONF_PATH_PREFIX_VOLUME, "Master", 0 },
+ { 'V', VCONF_PATH_PREFIX_VOLUME, "MasterHeadphone", 0 },
+ { 'V', VCONF_PATH_PREFIX_VOLUME, "MasterMuteOn", 0 },
+ { 'V', VCONF_PATH_PREFIX_VOLUME, "alarm", 1 },
+ { 'V', VCONF_PATH_PREFIX_VOLUME, "call", 1 },
+ { 'V', VCONF_PATH_PREFIX_VOLUME, "master", 1 },
+ { 'V', VCONF_PATH_PREFIX_VOLUME, "media", 1 },
+ { 'V', VCONF_PATH_PREFIX_VOLUME, "notification", 1 },
+ { 'V', VCONF_PATH_PREFIX_VOLUME, "ringtone", 1 },
+ { 'V', VCONF_PATH_PREFIX_VOLUME, "system", 1 },
+ { 'V', VCONF_PATH_PREFIX_VOLUME, "voice", 1 },
+ { 'V', VCONF_PATH_PREFIX_VOLUME, "voip", 1 },
+ };
+
+#endif
--- /dev/null
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2016 KimJeongYeon <jeongyeon.kim@samsung.com>
+
+ Based on module-gconf.c
+
+ 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 <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <pulse/xmalloc.h>
+#include <pulsecore/module.h>
+#include <pulsecore/core.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/log.h>
+#include <pulse/mainloop-api.h>
+#include <pulsecore/core-error.h>
+#include <pulsecore/start-child.h>
+
+#include "../communicator.h"
+#include "module-vconf-symdef.h"
+#include "hook-data.h"
+
+PA_MODULE_AUTHOR("KimJeongYeon");
+PA_MODULE_DESCRIPTION("VCONF Adapter");
+PA_MODULE_VERSION(PACKAGE_VERSION);
+PA_MODULE_LOAD_ONCE(true);
+
+#define BUF_MAX 2048
+
+struct userdata {
+ pa_core *core;
+ pa_module *module;
+
+ pid_t pid;
+
+ int fd;
+ int fd_type;
+ pa_io_event *io_event;
+
+ char buf[BUF_MAX];
+ size_t buf_fill;
+
+ pa_communicator *comm;
+};
+
+static int fill_buf(struct userdata *u) {
+ ssize_t r;
+ pa_assert(u);
+
+ if (u->buf_fill >= BUF_MAX) {
+ pa_log_error("read buffer overflow");
+ return -1;
+ }
+
+ if ((r = pa_read(u->fd, u->buf + u->buf_fill, BUF_MAX - u->buf_fill, &u->fd_type)) <= 0)
+ return -1;
+
+ u->buf_fill += (size_t) r;
+ return 0;
+}
+
+static int read_byte(struct userdata *u) {
+ int ret;
+ pa_assert(u);
+
+ if (u->buf_fill < 1)
+ if (fill_buf(u) < 0)
+ return -1;
+
+ ret = u->buf[0];
+ pa_assert(u->buf_fill > 0);
+ u->buf_fill--;
+ memmove(u->buf, u->buf+1, u->buf_fill);
+ return ret;
+}
+
+static char *read_string(struct userdata *u) {
+ pa_assert(u);
+
+ for (;;) {
+ char *e;
+
+ if ((e = memchr(u->buf, 0, u->buf_fill))) {
+ char *ret = pa_xstrdup(u->buf);
+ u->buf_fill -= (size_t) (e - u->buf +1);
+ memmove(u->buf, e+1, u->buf_fill);
+ return ret;
+ }
+
+ if (fill_buf(u) < 0)
+ return NULL;
+ }
+}
+
+static int handle_event(struct userdata *u) {
+ int opcode;
+ int ret = 0;
+
+ do {
+ if ((opcode = read_byte(u)) < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ break;
+ goto fail;
+ }
+
+ switch (opcode) {
+ case '!':
+ /* The helper tool is now initialized */
+ ret = 1;
+ pa_log_info("The helper tool is now initialized.");
+ break;
+
+ case 'V':
+ /* fall-through */
+
+ default: {
+ /* Default vconf changing events */
+ char *key, *value;
+ pa_module_vconf_hook_data_for_vconf_changed hook_data;
+
+ if (!(key = read_string(u)))
+ goto fail;
+ if (!(value = read_string(u))) {
+ pa_xfree(key);
+ goto fail;
+ }
+
+ pa_log_info("Vconf notified. (key:%s, value:%s)", key, value);
+
+ /* Hook msg from vconf helper */
+ memset(&hook_data, 0, sizeof(pa_module_vconf_hook_data_for_vconf_changed));
+ hook_data.key = key;
+ hook_data.value = value;
+ pa_hook_fire(pa_communicator_hook(u->comm, PA_COMMUNICATOR_HOOK_UPDATE_VCONF), &hook_data);
+
+ pa_xfree(key);
+ pa_xfree(value);
+ break;
+ }
+ }
+ } while (u->buf_fill > 0 && ret == 0);
+
+ return ret;
+
+fail:
+ pa_log_error("Unable to read or parse data from client.");
+ return -1;
+}
+
+static void io_event_cb(
+ pa_mainloop_api*a,
+ pa_io_event* e,
+ int fd,
+ pa_io_event_flags_t events,
+ void *userdata) {
+
+ struct userdata *u = userdata;
+
+ if (handle_event(u) < 0) {
+
+ if (u->io_event) {
+ u->core->mainloop->io_free(u->io_event);
+ u->io_event = NULL;
+ }
+
+ pa_module_unload_request(u->module, true);
+ }
+}
+
+int pa__init(pa_module *m) {
+ struct userdata *u;
+ int r;
+
+ pa_assert(m);
+
+ u = pa_xnew(struct userdata, 1);
+ u->core = m->core;
+ u->module = m;
+ m->userdata = u;
+ u->pid = (pid_t) -1;
+ u->fd = -1;
+ u->fd_type = 0;
+ u->io_event = NULL;
+ u->buf_fill = 0;
+ u->comm = pa_communicator_get(m->core);
+
+ if ((u->fd = pa_start_child_for_read(
+#if defined(__linux__) && !defined(__OPTIMIZE__)
+ pa_run_from_build_tree() ? PA_BUILDDIR "/vconf-helper" :
+#endif
+ PA_VCONF_HELPER, NULL, &u->pid)) < 0)
+ goto fail;
+
+ u->io_event = m->core->mainloop->io_new(
+ m->core->mainloop,
+ u->fd,
+ PA_IO_EVENT_INPUT,
+ io_event_cb,
+ u);
+
+ do {
+ if ((r = handle_event(u)) < 0)
+ goto fail;
+
+ /* Read until the client signalled us that it is ready with
+ * initialization */
+ } while (r != 1);
+
+ return 0;
+
+fail:
+ pa__done(m);
+ return -1;
+}
+
+void pa__done(pa_module *m) {
+ struct userdata *u;
+
+ pa_assert(m);
+
+ if (!(u = m->userdata))
+ return;
+
+ if (u->comm)
+ pa_communicator_unref(u->comm);
+
+ if (u->pid != (pid_t) -1) {
+ kill(u->pid, SIGTERM);
+
+ for (;;) {
+ if (waitpid(u->pid, NULL, 0) >= 0)
+ break;
+
+ if (errno != EINTR) {
+ pa_log_error("waitpid() failed: %s", pa_cstrerror(errno));
+ break;
+ }
+ }
+ }
+
+ if (u->io_event)
+ m->core->mainloop->io_free(u->io_event);
+
+ if (u->fd >= 0)
+ pa_close(u->fd);
+
+ pa_xfree(u);
+}
--- /dev/null
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2016 KimJeongYeon <jeongyeon.kim@samsung.com>
+
+ Based on gconf-helper.c
+
+ 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 <stdlib.h>
+#include <stdio.h>
+
+#include <vconf.h>
+#include <glib.h>
+
+#include "hook-data.h"
+
+#define VCONF_PATH_MAX 128
+
+static void vconf_callback(keynode_t *key, void *data) {
+ char buf[VCONF_PATH_MAX] = {0,};
+ struct vconf_item *vitem = (struct vconf_item *)data;
+ int idx;
+
+ if (!vitem)
+ return;
+
+ idx = vitem->prefix;
+
+ if (!strncmp(vconf_keynode_get_name(key), vconf_prefix[idx], strlen(vconf_prefix[idx]))) {
+ snprintf(buf, sizeof(buf), "%c%s", vitem->opcode, vconf_keynode_get_name(key));
+ fprintf(stdout, "%s%c", buf, 0); /* Send opcode + key + '\0'. */
+
+ switch (vconf_keynode_get_type(key)) {
+ case VCONF_TYPE_STRING:
+ snprintf(buf, sizeof(buf), "%s", vconf_keynode_get_str(key));
+ break;
+ case VCONF_TYPE_INT:
+ snprintf(buf, sizeof(buf), "%d", vconf_keynode_get_int(key));
+ break;
+ case VCONF_TYPE_DOUBLE:
+ snprintf(buf, sizeof(buf), "%f", vconf_keynode_get_dbl(key));
+ break;
+ case VCONF_TYPE_BOOL:
+ snprintf(buf, sizeof(buf), "%d", vconf_keynode_get_bool(key));
+ break;
+ default:
+ buf[0] = 0;
+ break;
+ }
+ fprintf(stdout, "%s%c", buf, 0); /* Send value + '\0'. */
+ }
+
+ fflush(stdout);
+}
+
+int main(int argc, char *argv[]) {
+ GMainLoop *g;
+ char vitem_key[VCONF_PATH_MAX] = {0,};
+ int i, idx;
+
+#if !defined(GLIB_VERSION_2_36)
+ g_type_init();
+#endif
+
+ /* Register vconf changing handler */
+ for (i = 0; i < sizeof(vitems) / sizeof(vitems[0]); i++) {
+ if (vitems[i].is_notify) {
+ idx = vitems[i].prefix;
+ snprintf(vitem_key, sizeof(vitem_key), "%s%s", vconf_prefix[idx], vitems[i].name);
+ vconf_notify_key_changed(vitem_key, vconf_callback, &vitems[i]);
+ }
+ }
+
+ /* Signal the parent that we are now initialized */
+ fprintf(stdout, "!");
+ fflush(stdout);
+
+ g = g_main_loop_new(NULL, FALSE);
+ g_main_loop_run(g);
+ g_main_loop_unref(g);
+
+ /* Unregister vconf changing handler */
+ for (i = 0; i < sizeof(vitems) / sizeof(vitems[0]); i++) {
+ if (vitems[i].is_notify) {
+ idx = vitems[i].prefix;
+ snprintf(vitem_key, sizeof(vitem_key), "%s%s", vconf_prefix[idx], vitems[i].name);
+ vconf_ignore_key_changed(vitem_key, vconf_callback);
+ }
+ }
+
+ return 0;
+}