2 * headphoned for the Nokia N8x0 and the N900
4 * The headphone daemon watches the state of the headphone
5 * plug (connected, disconnected) and carries out actions
6 * based on these events.
9 * * Send "pause" to the media player on disconnect
10 * * Maintain different volume settings for each state
12 * Initial working version: 2009-10-21
14 * Copyright (c) 2009-2010 Thomas Perl <thpinfo.com>
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this package; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35 #include <gconf/gconf-client.h>
37 #include <dbus/dbus.h>
42 #define STATE_FILE "/sys/devices/platform/gpio-switch/headphone/state"
43 #define STATE_CONNECTED_STR "connected"
44 #define STATE_DISCONNECTED_STR "disconnected"
46 #define GCONF_VOLUME_CONTROL "/apps/osso/sound/master_volume"
49 # define MEDIA_SERVER_SRVC "com.nokia.osso_media_server"
50 # define MEDIA_SERVER_PATH "/com/nokia/osso_media_server"
51 # define MEDIA_SERVER_INTF "com.nokia.osso_media_server.music"
53 # define MEDIA_SERVER_SRVC "com.nokia.mafw.renderer.Mafw-Gst-Renderer-Plugin.gstrenderer"
54 # define MEDIA_SERVER_PATH "/com/nokia/mafw/renderer/gstrenderer"
55 # define MEDIA_SERVER_INTF "com.nokia.mafw.renderer"
58 #define PANUCCI_SRVC "org.panucci.panucciInterface"
59 #define PANUCCI_PATH "/panucciInterface"
60 #define PANUCCI_INTF "org.panucci.panucciInterface"
62 #define MPLAYER_FIFO "/etc/headphoned/mplayer-input"
64 enum { STATE_UNKNOWN, STATE_CONNECTED, STATE_DISCONNECTED, STATE_COUNT };
68 DBusConnection* session_bus;
71 gint volume[STATE_COUNT];
76 GMainLoop* loop = NULL;
79 sig_handler (int sig G_GNUC_UNUSED)
81 if (loop && g_main_loop_is_running (loop)) {
82 g_main_loop_quit (loop);
87 on_volume_changed(GConfClient* client, guint gnxn_id, GConfEntry* entry,
90 Headphoned* headphoned = (Headphoned*)data;
91 headphoned->volume[headphoned->state] =
92 gconf_value_get_int(entry->value);
98 Headphoned* this = g_new0(Headphoned, 1);
100 this->osso = osso_initialize("headphoned", "1.0", FALSE, NULL);
101 assert(this->osso != NULL);
103 #ifdef ENABLE_VOLUME_CONTROL
104 this->client = gconf_client_get_default();
105 gconf_client_add_dir(this->client, GCONF_VOLUME_CONTROL,
106 GCONF_CLIENT_PRELOAD_NONE, NULL);
107 gconf_client_notify_add(this->client, GCONF_VOLUME_CONTROL,
108 on_volume_changed, this, NULL, NULL);
111 this->session_bus = (DBusConnection*)osso_get_dbus_connection(this->osso);
112 this->initial = TRUE;
118 on_file_changed(GIOChannel* source, GIOCondition condition, gpointer data)
120 Headphoned* headphoned = (Headphoned*)data;
121 #ifdef ENABLE_VOLUME_CONTROL
122 gint volume = headphoned->volume[headphoned->state];
127 g_io_channel_seek_position(source, 0, G_SEEK_SET, NULL);
128 g_io_channel_read_line(source, &result, NULL, NULL, NULL);
131 if (g_ascii_strcasecmp(result, STATE_CONNECTED_STR) == 0) {
132 headphoned->state = STATE_CONNECTED;
134 headphoned->state = STATE_DISCONNECTED;
135 #ifdef ENABLE_PAUSE_ON_DISCONNECT
136 if (headphoned->initial == FALSE) {
137 /* Nokia Media Player */
138 osso_rpc_run(headphoned->osso,
147 if (dbus_bus_name_has_owner(headphoned->session_bus,
150 osso_rpc_run(headphoned->osso,
160 if ((mplayer_fifo = open(MPLAYER_FIFO,
161 O_WRONLY | O_NONBLOCK)) != -1) {
162 write(mplayer_fifo, "pause\n", 6);
169 #ifdef ENABLE_VOLUME_CONTROL
170 gint new_volume = headphoned->volume[headphoned->state];
171 if (new_volume != volume) {
172 gconf_client_set_int(headphoned->client, GCONF_VOLUME_CONTROL,
174 /*gconf_client_suggest_sync(headphoned->client, NULL);
175 gconf_client_clear_cache(headphoned->client);*/
178 headphoned->initial = FALSE;
185 main(int argc, char* argv[])
187 Headphoned *headphoned;
190 signal(SIGINT, sig_handler);
191 signal(SIGQUIT, sig_handler);
192 signal(SIGTERM, sig_handler);
194 loop = g_main_loop_new(NULL, FALSE);
195 headphoned = headphoned_new();
197 GIOChannel* state = g_io_channel_new_file(STATE_FILE, "r", NULL);
198 g_io_add_watch(state, G_IO_PRI, on_file_changed, headphoned);
200 g_main_loop_run(loop);
202 #ifdef ENABLE_VOLUME_CONTROL
203 if (headphoned->client) {
204 gconf_client_remove_dir(headphoned->client, GCONF_VOLUME_CONTROL, NULL);
205 g_object_unref(headphoned->client);
210 g_io_channel_unref(state);
213 osso_deinitialize(headphoned->osso);