diff --git a/src/notify/event.c b/src/notify/event.c
index 021e5d1..12ed0d6 100644
--- a/src/notify/event.c
+++ b/src/notify/event.c
@@ -21,9 +21,11 @@
 #include <audacious/drct.h>
 #include <audacious/i18n.h>
 #include <audacious/playlist.h>
+#include <audacious/misc.h>
 #include <libaudcore/hook.h>
 #include <libaudgui/libaudgui-gtk.h>
 
+#include "config.h"
 #include "event.h"
 #include "osd.h"
 
@@ -37,6 +39,11 @@ static void clear (void)
     last_message = NULL;
 }
 
+static void update_button (void * unused, void * useless)
+{
+    osd_refresh ();
+}
+
 static void reshow (void)
 {
     if (! last_title || ! last_message)
@@ -46,7 +53,7 @@ static void reshow (void)
     if (pb)
         audgui_pixbuf_scale_within (& pb, 96);
 
-    osd_show (last_title, last_message, "audio-x-generic", pb);
+    osd_show (last_title, last_message, pb);
 
     if (pb)
         g_object_unref (pb);
@@ -57,7 +64,7 @@ static void update (void * unused, void * explicit)
     if (! aud_drct_get_playing () || ! aud_drct_get_ready ())
     {
         if (GPOINTER_TO_INT (explicit))
-            osd_show (_("Stopped"), _("Audacious is not playing."), NULL, NULL);
+            osd_show (_("Stopped"), _("Audacious is not playing."), NULL);
 
         return;
     }
@@ -107,6 +114,10 @@ void event_init (void)
     hook_associate ("playback ready", (HookFunction) update, GINT_TO_POINTER (FALSE));
     hook_associate ("playlist update", (HookFunction) update, GINT_TO_POINTER (FALSE));
     hook_associate ("current art ready", (HookFunction) reshow, NULL);
+    hook_associate ("playback pause", (HookFunction) update_button, NULL);
+    hook_associate ("playback unpause", (HookFunction) update_button, NULL);
+    hook_associate ("playback begin", (HookFunction) update_button, NULL);
+    hook_associate ("playback stop", (HookFunction) update_button, NULL);
     hook_associate ("playback begin", (HookFunction) clear, NULL);
     hook_associate ("playback stop", (HookFunction) clear, NULL);
 }
@@ -117,6 +128,10 @@ void event_uninit (void)
     hook_dissociate ("playback ready", (HookFunction) update);
     hook_dissociate ("playlist update", (HookFunction) update);
     hook_dissociate ("current art ready", (HookFunction) reshow);
+    hook_dissociate ("playback pause", (HookFunction) update_button);
+    hook_dissociate ("playback unpause", (HookFunction) update_button);
+    hook_dissociate ("playback begin", (HookFunction) update_button);
+    hook_dissociate ("playback stop", (HookFunction) update_button);
     hook_dissociate ("playback begin", (HookFunction) clear);
     hook_dissociate ("playback stop", (HookFunction) clear);
     clear ();
diff --git a/src/notify/notify.c b/src/notify/notify.c
index cac2201..f012cfe 100644
--- a/src/notify/notify.c
+++ b/src/notify/notify.c
@@ -23,7 +23,10 @@
 #include <audacious/i18n.h>
 #include <audacious/plugin.h>
 #include <audacious/debug.h>
+#include <audacious/preferences.h>
+#include <audacious/misc.h>
 
+#include "config.h"
 #include "event.h"
 #include "osd.h"
 
@@ -46,12 +49,31 @@ static const char plugin_about[] =
     "You should have received a copy of the GNU General Public License "
     "along with this program.  If not, see <http://www.gnu.org/licenses/>.");
 
+static const char * const notify_defaults[] = {
+ "actions", "TRUE",
+ NULL};
+
+
+static const PreferencesWidget notify_widgets[] = {
+ {WIDGET_CHK_BTN, N_("Activate controls inside of the notification"),
+ .cfg_type = VALUE_BOOLEAN, .csect = "notify", .cname = "actions"},
+};
+
+static const PluginPreferences notify_prefs = {
+ .widgets = notify_widgets,
+ .n_widgets = G_N_ELEMENTS (notify_widgets),
+ .apply = toggleaction
+};
+
+
+
 AUD_GENERAL_PLUGIN
 (
     .name = N_("Desktop Notifications"),
     .domain = PACKAGE,
     .about_text = plugin_about,
     .init = plugin_init,
+    .prefs = & notify_prefs,
     .cleanup = plugin_cleanup
 )
 
@@ -60,6 +82,7 @@ short plugin_active = 0;
 gboolean plugin_init (void)
 {
     AUDDBG("started!\n");
+    aud_config_set_defaults ("notify", notify_defaults);
     if(!osd_init()) {
         AUDDBG("osd_init failed!\n");
         return FALSE;
@@ -67,6 +90,7 @@ gboolean plugin_init (void)
     event_init();
 
     plugin_active = 1;
+    AUDDBG("Osd plugin initted\n");
     return TRUE;
 }
 
diff --git a/src/notify/osd.c b/src/notify/osd.c
index 0dbf1c6..29b56bf 100644
--- a/src/notify/osd.c
+++ b/src/notify/osd.c
@@ -17,55 +17,209 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <libaudcore/core.h>
+#include <libaudcore/hook.h>
+#include <audacious/debug.h>
+#include <audacious/i18n.h>
+#include <audacious/drct.h>
+#include <audacious/misc.h>
+#include <libnotify/notify.h>
 #include "osd.h"
 
 static NotifyNotification * notification = NULL;
+static gboolean actions_available = FALSE;
+static gboolean resident_notification = FALSE;
+
+
 
 bool_t osd_init()
 {
-    return notify_init ("Audacious");
+    if (notify_is_initted())
+    {
+        AUDDBG("Notify is already initted, that shouldn't happen\n");
+        return FALSE;
+    }
+    if (notify_init("Audacious"))
+    {
+        notification = notify_notification_new("Notification", NULL, NULL);
+
+        notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
+        notify_notification_set_hint (notification, "desktop-entry", g_variant_new_string ("audacious"));
+        notify_notification_set_category (notification, "x-gnome.music");
+
+        GList *server_caps;
+        server_caps = notify_get_server_caps ();
+
+        if (g_list_find_custom (server_caps, "actions", (GCompareFunc)g_strcmp0) && aud_get_bool ("notify", "actions"))
+        {
+            actions_available = TRUE;
+            if (g_list_find_custom (server_caps, "action-icons", (GCompareFunc)g_strcmp0))
+                notify_notification_set_hint (notification, "action-icons", g_variant_new_boolean (TRUE));
+            if (g_list_find_custom (server_caps, "persistence", (GCompareFunc)g_strcmp0) )
+            {
+                AUDDBG("Notification server supports persistence\n");
+                resident_notification = TRUE;
+                notify_notification_set_hint (notification, "resident", g_variant_new_boolean (TRUE));
+                notify_notification_set_hint (notification, "transient", g_variant_new_boolean (FALSE));
+            }
+        }
+        else
+        {
+            notify_notification_set_hint (notification, "resident", g_variant_new_boolean (FALSE));
+            notify_notification_set_hint (notification, "transient", g_variant_new_boolean (TRUE));
+        }
+        g_list_free_full(server_caps, g_free);
+        return TRUE;
+    }
+    else 
+        return FALSE;
 }
 
 void osd_uninit (void)
 {
     if (notification)
     {
+        GError *error = NULL;
+        if (notify_notification_close (notification, &error) == FALSE)
+            AUDDBG("%s!\n", error->message);
+        if(error)
+            g_error_free(error);
         g_object_unref (notification);
         notification = NULL;
     }
 
     notify_uninit();
+    AUDDBG("Notify uninitted\n");
 }
 
-static void osd_closed_handler (void)
+
+void goprevious (NotifyNotification *notification,
+            const char *action,
+            gpointer user_data)
 {
-    if (notification)
-    {
-        g_object_unref (notification);
-        notification = NULL;
-    }
+    aud_drct_pl_prev();
 }
 
-void osd_show (const char * title, const char * _message, const char * icon,
- GdkPixbuf * pixbuf)
+void gonext (NotifyNotification *notification,
+        const char *action,
+        gpointer user_data)
 {
-    char * message = g_markup_escape_text (_message, -1);
+    aud_drct_pl_next();
+}
 
-    if (pixbuf)
-        icon = NULL;
+void show_audacious (NotifyNotification *notification,
+        const char *action,
+        gpointer user_data)
+{
+    aud_interface_show(TRUE);
+}
 
-    if (notification)
-        notify_notification_update (notification, title, message, icon);
+void playpause (NotifyNotification *notification,
+           const char *action,
+           gpointer user_data)
+{
+    if(aud_drct_get_playing())
+    {aud_drct_pause();}
     else
+    {aud_drct_play();}
+}
+
+void osd_update_button(void){
+    if(actions_available){
+        gboolean paused = TRUE;
+        if (aud_drct_get_playing()) {paused = aud_drct_get_paused();}
+
+        notify_notification_clear_actions (notification);
+
+        notify_notification_add_action (notification,
+                    "media-skip-backward",
+                    N_("Previous"),
+                    NOTIFY_ACTION_CALLBACK(goprevious),
+                    NULL,
+                    NULL);
+
+        notify_notification_add_action (notification,
+                    paused ? "media-playback-start" : "media-playback-pause",
+                    paused ? N_("Play") : N_("Pause"),
+                    NOTIFY_ACTION_CALLBACK(playpause),
+                    NULL,
+                    NULL);
+
+        notify_notification_add_action (notification,
+                    "media-skip-forward",
+                    N_("Next"),
+                    NOTIFY_ACTION_CALLBACK(gonext),
+                    NULL,
+                    NULL);
+
+        notify_notification_add_action (notification,
+                    "default",
+                    N_("Show Audacious"),
+                    NOTIFY_ACTION_CALLBACK(show_audacious),
+                    NULL,
+                    NULL);
+    }
+}
+
+void osd_refresh(void){
+    osd_update_button();
+    if(resident_notification)
     {
-        notification = notify_notification_new (title, message, icon);
-        g_signal_connect (notification, "closed", (GCallback) osd_closed_handler, NULL);
+        GError *error = NULL;
+        if(!notify_notification_show(notification, &error))
+            AUDDBG("Error “%s” when trying to send notification\n", error->message);
+        if(error)
+            g_error_free(error);
     }
+}
+
+void osd_show (const gchar * title, const gchar * _message, GdkPixbuf *cover)
+{
+    gchar * message = g_markup_escape_text (_message, -1);
+    GError *error = NULL;
 
-    if (pixbuf)
-        notify_notification_set_icon_from_pixbuf (notification, pixbuf);
+    if(cover)
+        notify_notification_set_image_from_pixbuf(notification, cover);
 
-    notify_notification_show (notification, NULL);
+    osd_update_button();
+
+    if(!notify_notification_update(notification, title, message, "audacious"))
+         AUDDBG("Could not update osd!\n");
+
+    if(!notify_notification_show(notification, &error))
+        AUDDBG("Error “%s” when trying to send notification\n", error->message);
+    if(error)
+        g_error_free(error);
 
     g_free (message);
 }
+
+void toggleaction(){
+    GList *server_caps;
+    server_caps = notify_get_server_caps ();
+
+    if (g_list_find_custom (server_caps, "actions", (GCompareFunc)g_strcmp0) && aud_get_bool ("notify", "actions"))
+    {
+        actions_available = TRUE;
+        if (g_list_find_custom (server_caps, "action-icons", (GCompareFunc)g_strcmp0))
+            notify_notification_set_hint (notification, "action-icons", g_variant_new_boolean (TRUE));
+        if (g_list_find_custom (server_caps, "persistence", (GCompareFunc)g_strcmp0) )
+        {
+            AUDDBG("Notification server supports persistence\n");
+            resident_notification = TRUE;
+            notify_notification_set_hint (notification, "resident", g_variant_new_boolean (TRUE));
+            notify_notification_set_hint (notification, "transient", g_variant_new_boolean (FALSE));
+            osd_update_button();
+            notify_notification_show(notification, NULL);
+        }
+    }
+    else
+    {
+        actions_available = FALSE;
+        resident_notification = FALSE;
+        notify_notification_clear_actions (notification);
+        notify_notification_set_hint (notification, "resident", g_variant_new_boolean (FALSE));
+        notify_notification_set_hint (notification, "transient", g_variant_new_boolean (TRUE));
+        notify_notification_close (notification, NULL);
+    }
+}
diff --git a/src/notify/osd.h b/src/notify/osd.h
index dd7b82b..edf42c7 100644
--- a/src/notify/osd.h
+++ b/src/notify/osd.h
@@ -17,9 +17,8 @@
  * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <libaudcore/core.h>
-#include <libnotify/notify.h>
-
 bool_t osd_init (void);
 void osd_uninit (void);
-void osd_show (const char * title, const char * message, const char * icon, GdkPixbuf * pixbuf);
+void osd_show (const gchar *title, const gchar *message, GdkPixbuf *pixbuf);
+void osd_refresh (void);
+void toggleaction (void);
