Permalink
Browse files

Erlang NIF interface to libnotify desktop bubbles

Send notifications to your Ubuntu 10.04 desktop.
  • Loading branch information...
msantos committed Jul 28, 2010
0 parents commit e1041e56e1ea8b07ac8bcd32ba569d189ef14bc2
Showing with 451 additions and 0 deletions.
  1. +3 −0 .gitignore
  2. +6 −0 Emakefile
  3. +39 −0 Makefile
  4. +27 −0 README
  5. +169 −0 c_src/notify.c
  6. BIN priv/erlang-logo.png
  7. +6 −0 priv/rss.cfg
  8. +85 −0 src/notify.erl
  9. +116 −0 src/rss.erl
@@ -0,0 +1,3 @@
+*.[oa]
+*.beam
+*.swp
@@ -0,0 +1,6 @@
+{["src/*"],
+ [{i, "include"},
+ {outdir, "ebin"},
+ debug_info]
+}.
+
@@ -0,0 +1,39 @@
+
+ERL=erl
+APP=notify
+
+CC=gcc
+
+# Use "-m64" for 64-bit Erlang installs
+ARCH=-m32
+
+# Mac OS X
+#FLAGS=$(ARCH) -O3 -fPIC -bundle -flat_namespace -undefined suppress -fno-common
+
+# Linux
+FLAGS=-fPIC -shared
+
+ERL_ROOT=/usr/local/lib/erlang
+CFLAGS=-g -Wall
+
+LIB=-pthread -D_REENTRANT -I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include -I/usr/include/atk-1.0 -I/usr/include/cairo -I/usr/include/pango-1.0 -I/usr/include/gio-unix-2.0/ -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/pixman-1 -I/usr/include/freetype2 -I/usr/include/directfb -I/usr/include/libpng12 -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -L/lib -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0 -lgio-2.0 -lpangoft2-1.0 -lgdk_pixbuf-2.0 -lm -lpangocairo-1.0 -lcairo -lpango-1.0 -lfreetype -lfontconfig -lgmodule-2.0 -ldbus-glib-1 -ldbus-1 -lpthread -lgobject-2.0 -lgthread-2.0 -lrt -lglib-2.0 -lnotify
+
+all: dir erl nif
+
+dir:
+ -@mkdir -p priv/tmp ebin
+
+erl:
+ @$(ERL) -noinput +B \
+ -eval 'case make:all() of up_to_date -> halt(0); error -> halt(1) end.'
+
+nif:
+ (cd c_src && \
+ $(CC) $(ARCH) -g -Wall $(LIB) $(FLAGS) -o ../priv/notify.so \
+ notify.c -I $(ERL_ROOT)/usr/include/ )
+
+
+clean:
+ @rm -fv ebin/*.beam priv/$(APP) priv/$(APP).so c_src/*.a c_src/*.o
+
+
27 README
@@ -0,0 +1,27 @@
+
+An Erlang NIF interface to the libnotify library. libnotify is used to
+send desktop notification bubbles.
+
+HOW TO BUILD IT
+
+make
+
+HOW TO USE IT
+
+osd(Options) -> ok | enomem
+ Types Options = [Opt]
+ Opt = [{summary, string()}, {body, string()}, {icon, string()},
+ {category, string()}, {urgency, int()}, {timeout, int()}]
+
+
+EXAMPLES
+
+> notify:osd([]).
+> notify:osd([{summary, "hello"}, {body, "world"}]).
+
+> rss:start().
+
+TODO
+
+* support growl on Mac OS X
+
@@ -0,0 +1,169 @@
+/* Copyright (c) 2010, Michael Santos <michael.santos@gmail.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <string.h>
+#include <libnotify/notify.h>
+
+#include "erl_nif.h"
+
+
+static ERL_NIF_TERM atom_ok;
+static ERL_NIF_TERM atom_error;
+static ERL_NIF_TERM atom_nomem;
+
+static gchar *stralloc(ErlNifBinary *bin);
+void strfree(gchar *p);
+
+
+ static int
+load(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM load_info)
+{
+ char buf[1024];
+
+ if (enif_get_string(env, load_info, buf, sizeof(buf), ERL_NIF_LATIN1) < 1)
+ return (-1);
+
+ if (!notify_init(buf))
+ return (-1);
+
+ atom_ok = enif_make_atom(env, "ok");
+ atom_error = enif_make_atom(env, "error");
+ atom_nomem = enif_make_atom(env, "enomem");
+
+ return (0);
+}
+
+ void
+unload(ErlNifEnv *env, void *priv_data)
+{
+ notify_uninit();
+}
+
+
+ static ERL_NIF_TERM
+nif_notify(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[])
+{
+ ErlNifBinary summary;
+ ErlNifBinary body;
+ ErlNifBinary icon;
+
+ ErlNifBinary category;
+ int urgency = NOTIFY_URGENCY_NORMAL;
+ int timeout = 0;
+
+ gchar *s_summary = NULL;
+ gchar *s_body = NULL;
+ gchar *s_icon = NULL;
+ gchar *s_category = NULL;
+
+ NotifyNotification *notify = NULL;
+
+ ERL_NIF_TERM rv = atom_ok;
+
+
+ if (!enif_inspect_iolist_as_binary(env, argv[0], &summary))
+ return enif_make_badarg(env);
+
+ if (!enif_inspect_iolist_as_binary(env, argv[1], &body))
+ return enif_make_badarg(env);
+
+ if (!enif_inspect_iolist_as_binary(env, argv[2], &icon))
+ return enif_make_badarg(env);
+
+ if (!enif_inspect_iolist_as_binary(env, argv[3], &category))
+ return enif_make_badarg(env);
+
+ if (!enif_get_int(env, argv[4], &urgency))
+ return enif_make_badarg(env);
+
+ if (!enif_get_int(env, argv[5], &timeout))
+ return enif_make_badarg(env);
+
+ s_summary = stralloc(&summary);
+ s_body = stralloc(&body);
+ s_icon = stralloc(&icon);
+ s_category = stralloc(&category);
+
+ if ( (s_summary == NULL) || (s_body == NULL) ||
+ (s_icon == NULL) || (s_category == NULL)) {
+ rv = atom_nomem;
+ goto ERR;
+ }
+
+ notify = notify_notification_new(s_summary, s_body, s_icon, NULL);
+
+ notify_notification_set_category(notify, s_category);
+ notify_notification_set_urgency(notify, urgency);
+ notify_notification_set_timeout(notify, timeout);
+
+ notify_notification_show(notify, NULL);
+
+ g_object_unref(G_OBJECT(notify));
+
+ERR:
+ strfree(s_summary);
+ strfree(s_body);
+ strfree(s_icon);
+ strfree(s_category);
+
+ return rv;
+}
+
+
+ static gchar *
+stralloc(ErlNifBinary *bin)
+{
+ gchar *str = NULL;
+
+ str = (gchar *)calloc(bin->size+1, sizeof(gchar));
+ if (str == NULL)
+ return (NULL);
+
+ (void)memcpy(str, bin->data, bin->size);
+ return (str);
+}
+
+
+ void
+strfree(gchar *p)
+{
+ if (p)
+ free(p);
+}
+
+
+static ErlNifFunc nif_funcs[] = {
+ {"notify", 6, nif_notify}
+};
+
+ERL_NIF_INIT(notify, nif_funcs, load, NULL, NULL, unload)
+
+
Binary file not shown.
@@ -0,0 +1,6 @@
+[
+{feed, "http://news.ycombinator.com/rss"},
+{poll, 15},
+{number, 5}
+].
+
@@ -0,0 +1,85 @@
+%% Copyright (c) 2010, Michael Santos <michael.santos@gmail.com>
+%% All rights reserved.
+%%
+%% Redistribution and use in source and binary forms, with or without
+%% modification, are permitted provided that the following conditions
+%% are met:
+%%
+%% Redistributions of source code must retain the above copyright
+%% notice, this list of conditions and the following disclaimer.
+%%
+%% Redistributions in binary form must reproduce the above copyright
+%% notice, this list of conditions and the following disclaimer in the
+%% documentation and/or other materials provided with the distribution.
+%%
+%% Neither the name of the author nor the names of its contributors
+%% may be used to endorse or promote products derived from this software
+%% without specific prior written permission.
+%%
+%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+%% "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+%% LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+%% FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+%% COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+%% INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+%% BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+%% LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+%% CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+%% LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+%% ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+%% POSSIBILITY OF SUCH DAMAGE.
+-module(notify).
+
+-export([
+ osd/1, urgency/1,
+ privdir/1,
+ notify/6
+ ]).
+
+-define(NOTIFY_NAME, "erlang-notify").
+
+-define(NOTIFY_SUMMARY, "you ! Erlang.").
+-define(NOTIFY_BODY, "receive after 10000 -> ok end.").
+-define(NOTIFY_ICON, icon()). % or notification-message-im
+-define(NOTIFY_CATEGORY, "message").
+-define(NOTIFY_URGENCY, urgency(normal)). % NOTIFY_URGENCY_LOW, NOTIFY_URGENCY_NORMAL, NOTIFY_URGENCY_CRITICAL
+-define(NOTIFY_TIMEOUT, 10000). % 10 seconds
+
+-on_load(on_load/0).
+
+
+on_load() ->
+ erlang:load_nif(niflib(), ?NOTIFY_NAME).
+
+notify(_,_,_,_,_,_) ->
+ erlang:error(not_implemented).
+
+osd(Opt) when is_list(Opt) ->
+ Summary = proplists:get_value(summary, Opt, ?NOTIFY_SUMMARY),
+ Body = proplists:get_value(body, Opt, ?NOTIFY_BODY),
+ Icon = proplists:get_value(icon, Opt, ?NOTIFY_ICON),
+ Category = proplists:get_value(category, Opt, ?NOTIFY_CATEGORY),
+ Urgency = proplists:get_value(urgency, Opt, ?NOTIFY_URGENCY),
+ Timeout = proplists:get_value(timeout, Opt, ?NOTIFY_TIMEOUT),
+
+ notify(Summary, Body, Icon, Category, Urgency, Timeout).
+
+urgency(low) -> 0;
+urgency(normal) -> 1;
+urgency(critical) -> 2.
+
+privdir(File) ->
+ filename:join([
+ filename:dirname(code:which(?MODULE)),
+ "..",
+ "priv",
+ File
+ ]).
+
+
+icon() ->
+ "file://" ++ privdir("erlang-logo.png").
+
+niflib() ->
+ privdir(?MODULE).
+
Oops, something went wrong.

0 comments on commit e1041e5

Please sign in to comment.