diff --git a/daemon/cmd_unload_studio.c b/daemon/cmd_unload_studio.c index e7782cd3..9537c176 100644 --- a/daemon/cmd_unload_studio.c +++ b/daemon/cmd_unload_studio.c @@ -27,6 +27,7 @@ #include "cmd.h" #include "studio_internal.h" #include "control.h" +#include "../proxies/notify_proxy.h" #define cmd_ptr ((struct ladish_command *)context) @@ -51,6 +52,7 @@ static bool run(void * context) dbus_object_path_destroy(g_dbus_connection, g_studio.dbus_object); g_studio.dbus_object = NULL; emit_studio_disappeared(); + ladish_notify_simple(LADISH_NOTIFY_URGENCY_NORMAL, "Studio unloaded", NULL); } if (g_studio.name != NULL) diff --git a/daemon/main.c b/daemon/main.c index 31b21dc8..b2196162 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -43,6 +43,7 @@ #include "dirhelpers.h" #include "../proxies/a2j_proxy.h" #include "../proxies/jmcore_proxy.h" +#include "../proxies/notify_proxy.h" bool g_quit; const char * g_dbus_unique_name; @@ -293,11 +294,16 @@ int main(int argc, char ** argv, char ** envp) /* setup our SIGSEGV magic that prints nice stack in our logfile */ setup_sigsegv(); - if (!a2j_proxy_init()) + if (!ladish_notify_init("LADI Session Handler")) { goto uninit_dbus; } + if (!a2j_proxy_init()) + { + goto uninit_notify; + } + if (!jmcore_proxy_init()) { goto uninit_a2j; @@ -308,6 +314,8 @@ int main(int argc, char ** argv, char ** envp) goto uninit_jmcore; } + ladish_notify_simple(LADISH_NOTIFY_URGENCY_LOW, "LADI Session Handler daemon activated", NULL); + while (!g_quit) { dbus_connection_read_write_dispatch(g_dbus_connection, 50); @@ -316,6 +324,7 @@ int main(int argc, char ** argv, char ** envp) } emit_clean_exit(); + ladish_notify_simple(LADISH_NOTIFY_URGENCY_LOW, "LADI Session Handler daemon deactivated", NULL); ret = EXIT_SUCCESS; @@ -329,6 +338,9 @@ uninit_jmcore: uninit_a2j: a2j_proxy_uninit(); +uninit_notify: + ladish_notify_uninit(); + uninit_dbus: disconnect_dbus(); diff --git a/daemon/studio.c b/daemon/studio.c index 72de2a8a..9110484c 100644 --- a/daemon/studio.c +++ b/daemon/studio.c @@ -41,6 +41,7 @@ #include "escape.h" #include "studio.h" #include "../proxies/jmcore_proxy.h" +#include "../proxies/notify_proxy.h" #define STUDIOS_DIR "/studios/" char * g_studios_dir; @@ -101,6 +102,7 @@ studio_publish(void) g_studio.dbus_object = object; emit_studio_appeared(); + ladish_notify_simple(LADISH_NOTIFY_URGENCY_NORMAL, "Studio loaded", NULL); return true; } @@ -273,6 +275,7 @@ void on_event_jack_started(void) ladish_app_supervisor_autorun(g_studio.app_supervisor); emit_studio_started(); + ladish_notify_simple(LADISH_NOTIFY_URGENCY_NORMAL, "Studio started", NULL); } static void on_jack_stopped_internal(void) @@ -292,14 +295,15 @@ static void on_jack_stopped_internal(void) void on_event_jack_stopped(void) { - emit_studio_stopped(); - on_jack_stopped_internal(); + emit_studio_stopped(); + on_jack_stopped_internal(); + ladish_notify_simple(LADISH_NOTIFY_URGENCY_NORMAL, "Studio stopped", NULL); } void handle_unexpected_jack_server_stop(void) { - emit_studio_crashed(); - on_jack_stopped_internal(); + emit_studio_crashed(); + on_jack_stopped_internal(); /* TODO: if user wants, restart jack server and reconnect all jack apps to it */ } @@ -361,6 +365,11 @@ void studio_run(void) log_error("JACK stopped unexpectedly."); log_error("Save your work, then unload and reload the studio."); + ladish_notify_simple( + LADISH_NOTIFY_URGENCY_HIGH, + "Studio crashed", + "JACK stopped unexpectedly.\n\n" + "Save your work, then unload and reload the studio."); handle_unexpected_jack_server_stop(); } } @@ -374,6 +383,11 @@ void studio_run(void) /* jack was started, this probably means that jackdbus has crashed */ log_error("JACK disappeared unexpectedly. Maybe it crashed."); log_error("Save your work, then unload and reload the studio."); + ladish_notify_simple( + LADISH_NOTIFY_URGENCY_HIGH, + "Studio crashed", + "JACK disappeared unexpectedly. Maybe it crashed.\n\n" + "Save your work, then unload and reload the studio."); ladish_environment_reset_stealth(&g_studio.env_store, ladish_environment_jack_server_started); studio_iterate_virtual_graphs(NULL, hide_vgraph_non_virtual); diff --git a/proxies/notify_proxy.c b/proxies/notify_proxy.c new file mode 100644 index 00000000..3da776ba --- /dev/null +++ b/proxies/notify_proxy.c @@ -0,0 +1,175 @@ +/* -*- Mode: C ; c-basic-offset: 2 -*- */ +/* + * LADI Session Handler (ladish) + * + * Copyright (C) 2010 Nedko Arnaudov + * + ************************************************************************** + * This file contains the code for sending notifications to user + ************************************************************************** + * + * LADI Session Handler is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * LADI Session Handler 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 General Public License + * along with LADI Session Handler. If not, see + * or write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "notify_proxy.h" + +#define NOTIFY_SERVICE "org.freedesktop.Notifications" +#define NOTIFY_OBJECT "/org/freedesktop/Notifications" +#define NOTIFY_IFACE "org.freedesktop.Notifications" +#define NOTIFY_METHOD_NOTIFY "Notify" + +static char * g_notify_app_name; + +bool ladish_notify_init(const char * app_name) +{ + const char * name; + const char * vendor; + const char * version; + const char * spec_version; + + g_notify_app_name = strdup(app_name); + if (g_notify_app_name == NULL) + { + log_error("strdup() failed for app name"); + return false; + } + + if (dbus_call(NOTIFY_SERVICE, NOTIFY_OBJECT, NOTIFY_IFACE, "GetServerInformation", "", "ssss", &name, &vendor, &version, &spec_version)) + { + log_info("Sending notifications to '%s' '%s' (%s, %s)", vendor, name, version, spec_version); + } + + return true; +} + +void ladish_notify_uninit(void) +{ + free(g_notify_app_name); +} + +void ladish_notify_simple(uint8_t urgency, const char * summary, const char * body) +{ + DBusMessage * request_ptr; + /* DBusMessage * reply_ptr; */ + DBusMessageIter iter; + DBusMessageIter array_iter; + DBusMessageIter dict_iter; + const char * str_value; + uint32_t uint32_value; + int32_t int32_value; + + request_ptr = dbus_message_new_method_call(NOTIFY_SERVICE, NOTIFY_OBJECT, NOTIFY_IFACE, NOTIFY_METHOD_NOTIFY); + if (request_ptr == NULL) + { + log_error("dbus_message_new_method_call() failed."); + goto exit; + } + + dbus_message_iter_init_append(request_ptr, &iter); + + /* app_name */ + str_value = g_notify_app_name; + if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &str_value)) + { + log_error("dbus_message_iter_append_basic() failed."); + goto free_request; + } + + /* replaces_id */ + uint32_value = 0; + if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, &uint32_value)) + { + log_error("dbus_message_iter_append_basic() failed."); + goto free_request; + } + + /* app_icon */ + str_value = ""; + if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &str_value)) + { + log_error("dbus_message_iter_append_basic() failed."); + goto free_request; + } + + /* summary */ + str_value = summary; + if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &str_value)) + { + log_error("dbus_message_iter_append_basic() failed."); + goto free_request; + } + + /* body */ + str_value = body == NULL ? "" : body; + if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &str_value)) + { + log_error("dbus_message_iter_append_basic() failed."); + goto free_request; + } + + /* actions */ + if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING, &array_iter)) + { + log_error("dbus_message_iter_open_container() failed."); + goto free_request; + } + + if (!dbus_message_iter_close_container(&iter, &array_iter)) + { + log_error("dbus_message_iter_close_container() failed."); + goto free_request; + } + + /* hints */ + if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &dict_iter)) + { + log_error("dbus_message_iter_open_container() failed."); + goto free_request; + } + + if (!dbus_iter_append_dict_entry(&dict_iter, DBUS_TYPE_BYTE, "urgency", &urgency, 0)) + { + log_error("dbus_iter_append_dict_entry() failed."); + goto free_request; + } + + if (!dbus_message_iter_close_container(&iter, &dict_iter)) + { + log_error("dbus_message_iter_close_container() failed."); + goto free_request; + } + + /* expire_timeout */ + int32_value = urgency == LADISH_NOTIFY_URGENCY_HIGH ? 0 : -1; + if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &int32_value)) + { + log_error("dbus_message_iter_append_basic() failed."); + goto free_request; + } + + if (!dbus_call(NOTIFY_SERVICE, NOTIFY_OBJECT, NOTIFY_IFACE, NOTIFY_METHOD_NOTIFY, NULL, request_ptr, "u", &uint32_value)) + { + //log_error("Notify() dbus call failed."); + goto free_request; + } + + //log_info("notify ID is %"PRIu32, uint32_value); + +free_request: + dbus_message_unref(request_ptr); +exit: + return; +} diff --git a/proxies/notify_proxy.h b/proxies/notify_proxy.h new file mode 100644 index 00000000..b454fadc --- /dev/null +++ b/proxies/notify_proxy.h @@ -0,0 +1,40 @@ +/* -*- Mode: C ; c-basic-offset: 2 -*- */ +/* + * LADI Session Handler (ladish) + * + * Copyright (C) 2010 Nedko Arnaudov + * + ************************************************************************** + * This file contains interface to code for sending notifications to user + ************************************************************************** + * + * LADI Session Handler is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * LADI Session Handler 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 General Public License + * along with LADI Session Handler. If not, see + * or write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef NOTIFY_PROXY_H__9C284CDE_3AC0_4F3E_A2C3_10ADF2CBDE46__INCLUDED +#define NOTIFY_PROXY_H__9C284CDE_3AC0_4F3E_A2C3_10ADF2CBDE46__INCLUDED + +#include "common.h" + +#define LADISH_NOTIFY_URGENCY_LOW 0 +#define LADISH_NOTIFY_URGENCY_NORMAL 1 +#define LADISH_NOTIFY_URGENCY_HIGH 2 + +bool ladish_notify_init(const char * app_name); +void ladish_notify_uninit(void); +void ladish_notify_simple(uint8_t urgency, const char * summary, const char * body); /* body can be NULL */ + +#endif /* #ifndef NOTIFY_PROXY_H__9C284CDE_3AC0_4F3E_A2C3_10ADF2CBDE46__INCLUDED */ diff --git a/wscript b/wscript index 2367fd47..8e88422c 100644 --- a/wscript +++ b/wscript @@ -240,6 +240,7 @@ def build(bld): 'graph_proxy.c', 'a2j_proxy.c', "jmcore_proxy.c", + "notify_proxy.c", ]: daemon.source.append(os.path.join("proxies", source))