new dbus helper function: dbus_call_simple()
[ladish.git] / daemon / main.c
blob2ee8572f6e087a90f7267b5f84f40e24e16b9bc4
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2008, 2009 Nedko Arnaudov <nedko@arnaudov.name>
6 * Copyright (C) 2008 Juuso Alasuutari <juuso.alasuutari@gmail.com>
7 * Copyright (C) 2002 Robert Ham <rah@bash.sh>
9 **************************************************************************
10 * This file contains the code that implements main() and other top-level functionality
11 **************************************************************************
13 * LADI Session Handler is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * LADI Session Handler is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
25 * or write to the Free Software Foundation, Inc.,
26 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include "common.h"
31 #include <stdlib.h>
32 #include <signal.h>
33 #include <sys/stat.h>
35 #include "version.h" /* git version define */
36 #include "proctitle.h"
37 #include "loader.h"
38 #include "sigsegv.h"
39 #include "dbus_iface_control.h"
40 #include "jack.h"
41 #include "studio.h"
43 bool g_quit;
44 const char * g_dbus_unique_name;
45 object_path_t * g_control_object;
46 studio_handle g_studio;
48 #if 0
49 static DBusHandlerResult lashd_client_disconnect_handler(DBusConnection * connection, DBusMessage * message, void * data)
51 /* If the message isn't a signal the object path handler may use it */
52 if (dbus_message_get_type(message) != DBUS_MESSAGE_TYPE_SIGNAL)
54 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
57 const char *member, *name, *old_name;
58 struct lash_client *client;
59 DBusError err;
61 if (!(member = dbus_message_get_member(message)))
63 lash_error("Received JACK signal with NULL member");
64 return DBUS_HANDLER_RESULT_HANDLED;
67 if (strcmp(member, "NameOwnerChanged") != 0)
69 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
72 dbus_error_init(&err);
74 if (!dbus_message_get_args(message, &err,
75 DBUS_TYPE_STRING, &name,
76 DBUS_TYPE_STRING, &old_name,
77 DBUS_TYPE_INVALID))
79 lash_error("Cannot get message arguments: %s",
80 err.message);
81 dbus_error_free(&err);
82 return DBUS_HANDLER_RESULT_HANDLED;
85 client = server_find_client_by_dbus_name(old_name);
86 if (client)
88 client_disconnected(client);
89 return DBUS_HANDLER_RESULT_HANDLED;
92 else
94 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
98 dbus_bus_add_match(
99 service->connection,
100 "type='signal'"
101 ",sender='org.freedesktop.DBus'"
102 ",path='/org/freedesktop/DBus'"
103 ",interface='org.freedesktop.DBus'"
104 ",member='NameOwnerChanged'"
105 ",arg2=''",
106 &err);
107 if (dbus_error_is_set(&err))
109 lash_error("Failed to add D-Bus match rule: %s", err.message);
110 dbus_error_free(&err);
111 goto fail;
114 if (!dbus_connection_add_filter(service->connection, lashd_client_disconnect_handler, NULL, NULL))
116 lash_error("Failed to add D-Bus filter");
117 goto fail;
119 #endif
121 static bool connect_dbus(void)
123 int ret;
125 g_dbus_connection = dbus_bus_get(DBUS_BUS_SESSION, &g_dbus_error);
126 if (dbus_error_is_set(&g_dbus_error))
128 lash_error("Failed to get bus: %s", g_dbus_error.message);
129 dbus_error_free(&g_dbus_error);
130 goto fail;
133 g_dbus_unique_name = dbus_bus_get_unique_name(g_dbus_connection);
134 if (g_dbus_unique_name == NULL)
136 lash_error("Failed to read unique bus name");
137 goto unref_connection;
140 ret = dbus_bus_request_name(g_dbus_connection, DBUS_NAME_BASE, DBUS_NAME_FLAG_DO_NOT_QUEUE, &g_dbus_error);
141 if (ret == -1)
143 lash_error("Failed to acquire bus name: %s", g_dbus_error.message);
144 dbus_error_free(&g_dbus_error);
145 goto unref_connection;
148 if (ret == DBUS_REQUEST_NAME_REPLY_EXISTS)
150 lash_error("Requested connection name already exists");
151 goto unref_connection;
154 g_control_object = object_path_new(CONTROL_OBJECT_PATH, NULL, 1, &g_lashd_interface_control, NULL);
155 if (g_control_object == NULL)
157 goto unref_connection;
160 if (!object_path_register(g_dbus_connection, g_control_object))
162 goto destroy_control_object;
165 return true;
167 destroy_control_object:
168 object_path_destroy(g_dbus_connection, g_control_object);
169 unref_connection:
170 dbus_connection_unref(g_dbus_connection);
172 fail:
173 return false;
176 static void disconnect_dbus(void)
178 object_path_destroy(g_dbus_connection, g_control_object);
179 dbus_connection_unref(g_dbus_connection);
182 static void on_child_exit(pid_t pid)
184 //client_disconnected(server_find_client_by_pid(child_ptr->pid));
187 void term_signal_handler(int signum)
189 lash_info("Caught signal %d (%s), terminating", signum, strsignal(signum));
190 g_quit = true;
193 bool install_term_signal_handler(int signum, bool ignore_if_already_ignored)
195 sig_t sigh;
197 sigh = signal(signum, term_signal_handler);
198 if (sigh == SIG_ERR)
200 lash_error("signal() failed to install handler function for signal %d.", signum);
201 return false;
204 if (sigh == SIG_IGN && ignore_if_already_ignored)
206 signal(SIGTERM, SIG_IGN);
209 return true;
212 int main(int argc, char ** argv, char ** envp)
214 struct stat st;
215 char timestamp_str[26];
216 int ret;
218 st.st_mtime = 0;
219 stat(argv[0], &st);
220 ctime_r(&st.st_mtime, timestamp_str);
221 timestamp_str[24] = 0;
223 lash_init_setproctitle(argc, argv, envp);
225 dbus_threads_init_default();
227 lash_info("------------------");
228 lash_info("LADI session handler activated. Version %s (%s) built on %s", PACKAGE_VERSION, GIT_VERSION, timestamp_str);
230 ret = EXIT_FAILURE;
232 loader_init(on_child_exit);
234 if (!connect_dbus())
236 lash_error("Failed to connecto to D-Bus");
237 goto uninit_loader;
240 /* install the signal handlers */
241 install_term_signal_handler(SIGTERM, false);
242 install_term_signal_handler(SIGINT, true);
243 install_term_signal_handler(SIGHUP, true);
244 if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
246 lash_error("signal(SIGPIPE, SIG_IGN).");
249 /* setup our SIGSEGV magic that prints nice stack in our logfile */
250 setup_sigsegv();
252 if (!jack_init())
254 goto uninit_dbus;
257 while (!g_quit)
259 dbus_connection_read_write_dispatch(g_dbus_connection, 50);
260 loader_run();
263 if (g_studio != NULL)
265 studio_destroy(g_studio);
266 emit_studio_disappeared();
269 ret = EXIT_SUCCESS;
271 lash_debug("Finished, cleaning up");
273 uninit_dbus:
274 jack_uninit();
276 disconnect_dbus();
278 uninit_loader:
279 loader_uninit();
281 lash_debug("Cleaned up, exiting");
283 lash_info("LADI session handler deactivated");
284 lash_info("------------------");
286 exit(EXIT_SUCCESS);