/** * @file notify-send.c A tool for sending notifications. * * Copyright (C) 2004 Christian Hammond. * * This program 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. * * This program 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 this program; if not, write to the Free * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ #include #include #include #include #include #include #include #define N_(x) (x) #define GETTEXT_PACKAGE NULL static NotifyUrgency urgency = NOTIFY_URGENCY_NORMAL; static gboolean g_option_arg_urgency_cb(const gchar *option_name, const gchar *value, gpointer data, GError **error) { if (value != NULL) { if (!strcasecmp(value, "low")) urgency = NOTIFY_URGENCY_LOW; else if (!strcasecmp(value, "normal")) urgency = NOTIFY_URGENCY_NORMAL; else if (!strcasecmp(value, "critical")) urgency = NOTIFY_URGENCY_CRITICAL; else { *error = g_error_new(G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, N_("Unknown urgency %s specified. " "Known urgency levels: low, " "normal, critical."), value); return FALSE; } } return TRUE; } static gboolean notify_notification_set_hint_variant(NotifyNotification *notification, const gchar *type, const gchar *key, const gchar *value, GError **error) { static gboolean conv_error = FALSE; if (!strcasecmp(type, "string")) { notify_notification_set_hint_string(notification, key, value); } else if (!strcasecmp(type, "int")) { if (!g_ascii_isdigit(*value)) conv_error = TRUE; else { gint h_int = (gint)g_ascii_strtoull(value, NULL, 10); notify_notification_set_hint_int32(notification, key, h_int); } } else if (!strcasecmp(type, "double")) { if (!g_ascii_isdigit(*value)) conv_error = TRUE; else { gdouble h_double = g_strtod(value, NULL); notify_notification_set_hint_double(notification, key, h_double); } } else if (!strcasecmp(type, "byte")) { gint h_byte = (gint)g_ascii_strtoull(value, NULL, 10); if (h_byte < 0 || h_byte > 0xFF) conv_error = TRUE; else { notify_notification_set_hint_byte(notification, key, (guchar)h_byte); } } else { *error = g_error_new(G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, N_("Invalid hint type \"%s\". Valid types " "are int, double, string and byte."), type); return FALSE; } if (conv_error) { *error = g_error_new(G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, N_("Value \"%s\" of hint \"%s\" could not be " "parsed as type \"%s\"."), value, key, type); return FALSE; } return TRUE; } int main(int argc, char *argv[]) { static const gchar *summary = NULL; static const gchar *body = ""; static const gchar *type = NULL; static gchar *icon_str = NULL; static gchar *icons = NULL; static gchar **n_text = NULL; static gchar **hints = NULL; static gboolean do_version = FALSE; static gboolean hint_error = FALSE; static glong expire_timeout = NOTIFY_EXPIRES_DEFAULT; GOptionContext *opt_ctx; NotifyNotification *notify; GError *error = NULL; gboolean retval; static const GOptionEntry entries[] = { { "urgency", 'u', 0, G_OPTION_ARG_CALLBACK, g_option_arg_urgency_cb, N_("Specifies the urgency level (low, normal, critical)."), N_("LEVEL") }, { "expire-time", 't', 0,G_OPTION_ARG_INT, &expire_timeout, N_("Specifies the timeout in milliseconds at which to expire the " "notification."), N_("TIME") }, { "icon", 'i', 0, G_OPTION_ARG_FILENAME, &icons, N_("Specifies an icon filename or stock icon to display."), N_("ICON[,ICON...]") }, { "category", 'c', 0, G_OPTION_ARG_FILENAME, &type, N_("Specifies the notification category."), N_("TYPE[,TYPE...]") }, { "hint", 'h', 0, G_OPTION_ARG_FILENAME_ARRAY, &hints, N_("Specifies basic extra data to pass. Valid types are int, double, string and byte."), N_("TYPE:NAME:VALUE") }, { "version", 'v', 0, G_OPTION_ARG_NONE, &do_version, N_("Version of the package."), NULL }, { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &n_text, NULL, NULL }, { NULL } }; g_type_init(); g_set_prgname(argv[0]); opt_ctx = g_option_context_new(N_(" [BODY] - " "create a notification")); g_option_context_add_main_entries(opt_ctx, entries, GETTEXT_PACKAGE); retval = g_option_context_parse(opt_ctx, &argc, &argv, &error); g_option_context_free(opt_ctx); if (!retval) { fprintf(stderr, "%s\n", error->message); g_error_free(error); exit(1); } if (do_version) { g_printf("%s %s\n", g_get_prgname(), VERSION); exit(0); } if (n_text != NULL && n_text[0] != NULL && *n_text[0] != '\0') summary = n_text[0]; if (summary == NULL) { fprintf(stderr, "%s\n", N_("No summary specified.")); exit(1); } if (n_text[1] != NULL) { body = n_text[1]; if (n_text[2] != NULL) { fprintf(stderr, "%s\n", N_("Invalid number of options.")); exit(1); } } if (icons != NULL) { char *c; /* XXX */ if((c = strchr(icons, ',')) != NULL) *c = '\0'; icon_str = icons; } if (!notify_init("notify-send")) exit(1); notify = notify_notification_new(summary, body, icon_str, NULL); notify_notification_set_category(notify, type); notify_notification_set_urgency(notify, urgency); notify_notification_set_timeout(notify, expire_timeout); // Set hints if (hints != NULL) { gint i = 0; gint l; gchar *hint = NULL; gchar **tokens = NULL; while ((hint = hints[i++])) { tokens = g_strsplit(hint, ":", -1); l = g_strv_length(tokens); if (l != 3) { fprintf(stderr, "%s\n", N_("Invalid hint syntax specified. " "Use TYPE:NAME:VALUE.")); hint_error = TRUE; } else { retval = notify_notification_set_hint_variant( notify, tokens[0], tokens[1], tokens[2], &error); if (!retval) { fprintf(stderr, "%s\n", error->message); g_error_free(error); hint_error = TRUE; } } g_strfreev(tokens); if (hint_error) break; } } if (!hint_error) notify_notification_show(notify, NULL); g_object_unref(G_OBJECT(notify)); notify_uninit(); exit(hint_error); }