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
);