2 This file is part of PulseAudio.
4 Copyright 2016 Seungbae Shin <seungbae.shin@samsung.com>
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2.1 of the License,
9 or (at your option) any later version.
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with PulseAudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
34 #include <pulse/xmalloc.h>
35 #include <pulse/proplist.h>
37 #include <pulsecore/module.h>
38 #include <pulsecore/log.h>
39 #include <pulsecore/namereg.h>
40 #include <pulsecore/sink.h>
41 #include <pulsecore/modargs.h>
42 #include <pulsecore/macro.h>
43 #include <pulsecore/core-util.h>
44 #include <pulsecore/core-error.h>
45 #include <pulsecore/dbus-shared.h>
46 #include <pulsecore/protocol-dbus.h>
47 #include <pulsecore/dbus-util.h>
48 #include <pulsecore/core-scache.h>
50 #include "module-poweroff-symdef.h"
52 #include "hal-interface.h"
54 PA_MODULE_AUTHOR("Seungbae Shin");
55 PA_MODULE_DESCRIPTION("Poweroff module");
56 PA_MODULE_VERSION(PACKAGE_VERSION);
57 PA_MODULE_LOAD_ONCE(true);
59 #define INTERFACE_NAME "org.tizen.system.deviced.PowerOff"
60 #define SIGNAL_NAME "ChangeState"
61 #define FILTER_POWEROFF "type='signal', interface='"INTERFACE_NAME"', member='"SIGNAL_NAME"'"
62 #define BOOT_GAIN_TYPE "booting"
64 #define STREAM_ROLE_RADIO "radio"
66 enum deviced_poweroff_type {
67 DEVICED_POWER_OFF_NONE = 0,
68 DEVICED_POWER_OFF_POPUP,
69 DEVICED_POWER_OFF_DIRECT,
70 DEVICED_POWER_OFF_RESTART,
75 pa_dbus_connection *dbus_conn;
76 pa_hal_interface *hal_interface;
78 pa_hook_slot *sink_input_new_slot;
81 static void mute_all_streams(struct userdata *u)
84 pa_sink_input *si = NULL;
85 const char *media_role = NULL;
86 hal_route_option route_option;
88 PA_IDXSET_FOREACH(si, u->module->core->sink_inputs, idx) {
89 pa_log_info("POWEROFF : mute sink-input(%d)", idx);
91 /* FIXME : Any exceptions for mute? */
92 pa_sink_input_set_mute(si, true, false);
94 /* Mute Radio via HAL if exists */
95 media_role = pa_proplist_gets(si->proplist, PA_PROP_MEDIA_ROLE);
96 if (pa_safe_streq(media_role, STREAM_ROLE_RADIO)) {
97 pa_log_info(" sink-input(%d) is radio, let HAL mute for poweroff!!", si->index);
98 memset(&route_option, 0, sizeof(hal_route_option));
99 route_option.role = STREAM_ROLE_RADIO;
100 route_option.name = "mute";
101 route_option.value = 1;
102 pa_hal_interface_update_route_option(u->hal_interface, &route_option);
107 static pa_hook_result_t sink_input_new_cb(pa_core *core, pa_sink_input_new_data *new_data, struct userdata *u) {
108 const char *vol_gain_type = NULL;
110 pa_core_assert_ref(core);
117 vol_gain_type = pa_proplist_gets(new_data->proplist, PA_PROP_MEDIA_TIZEN_VOLUME_GAIN_TYPE);
118 if (pa_safe_streq(vol_gain_type, BOOT_GAIN_TYPE)) {
119 pa_log_info(" ignore mute for gain [%s]", BOOT_GAIN_TYPE);
121 pa_log_info(" Mute sink-input due to POWEROFF");
122 pa_sink_input_new_data_set_muted(new_data, true);
128 static DBusHandlerResult _dbus_filter_device_detect_handler(DBusConnection *c, DBusMessage *s, void *userdata) {
129 struct userdata *u = (struct userdata *)userdata;
134 if (dbus_message_get_type(s) != DBUS_MESSAGE_TYPE_SIGNAL)
135 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
137 pa_log_debug("DBus device detect handler received msg");
138 pa_log_debug("path : %s", dbus_message_get_path(s));
139 pa_log_debug("interface : %s", dbus_message_get_interface(s));
140 pa_log_debug("member : %s", dbus_message_get_member(s));
141 pa_log_debug("signature : %s", dbus_message_get_signature(s));
143 if (dbus_message_is_signal(s, INTERFACE_NAME, SIGNAL_NAME)) {
144 if (dbus_message_get_args(s, NULL, DBUS_TYPE_INT32, &state, DBUS_TYPE_INVALID)) {
145 if (state == DEVICED_POWER_OFF_DIRECT ||
146 state == DEVICED_POWER_OFF_RESTART) {
147 const char* mode_str[] = { "None", "Popup", "Direct", "Restart" };
148 pa_log_warn("---- PowerOff : %s ----", mode_str[state]);
149 u->is_poweroff = true;
153 pa_log_error("failed to parse state, do nothing!!!");
155 return DBUS_HANDLER_RESULT_HANDLED;
158 pa_log_debug("Unknown message, do not handle this");
159 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
162 static int _watch_signals(struct userdata *u) {
166 pa_assert(u->dbus_conn);
168 dbus_error_init(&error);
170 pa_log_debug("Watch Dbus signals");
172 if (!dbus_connection_add_filter(pa_dbus_connection_get(u->dbus_conn), _dbus_filter_device_detect_handler, u, NULL)) {
173 pa_log_error("Unable to add D-Bus filter");
177 if (pa_dbus_add_matches(pa_dbus_connection_get(u->dbus_conn), &error, FILTER_POWEROFF, NULL) < 0) {
178 pa_log_error("Unable to subscribe to signals: %s: %s", error.name, error.message);
179 dbus_error_free(&error);
186 static void _unwatch_signals(struct userdata *u) {
187 pa_log_debug("Unwatch Dbus signals");
190 pa_assert(u->dbus_conn);
192 pa_dbus_remove_matches(pa_dbus_connection_get(u->dbus_conn), FILTER_POWEROFF, NULL);
193 dbus_connection_remove_filter(pa_dbus_connection_get(u->dbus_conn), _dbus_filter_device_detect_handler, u);
196 static int _dbus_init(struct userdata *u) {
198 pa_dbus_connection *connection = NULL;
202 dbus_error_init(&error);
204 pa_log_debug("Dbus init");
206 if (!(connection = pa_dbus_bus_get(u->module->core, DBUS_BUS_SYSTEM, &error)) || dbus_error_is_set(&error)) {
208 pa_dbus_connection_unref(connection);
210 pa_log_error("Unable to contact D-Bus system bus: %s: %s", error.name, error.message);
211 dbus_error_free(&error);
214 pa_log_debug("Got dbus connection %p", connection);
215 u->dbus_conn = connection;
217 if (_watch_signals(u) < 0)
218 pa_log_error("dbus watch signals failed");
220 pa_log_debug("dbus ready to get signals");
225 static void _dbus_deinit(struct userdata *u) {
228 pa_log_debug("Dbus deinit");
233 pa_dbus_connection_unref(u->dbus_conn);
238 int pa__init(pa_module *m) {
243 m->userdata = u = pa_xnew0(struct userdata, 1);
246 u->is_poweroff = false;
248 if (_dbus_init(u) == -1) {
253 u->hal_interface = pa_hal_interface_get(u->module->core);
254 u->sink_input_new_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_NEW], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_new_cb, u);
259 void pa__done(pa_module *m) {
264 if (!(u = m->userdata))
267 if (u->sink_input_new_slot)
268 pa_hook_slot_free(u->sink_input_new_slot);
270 if (u->hal_interface)
271 pa_hal_interface_unref(u->hal_interface);