diff --git a/src/notify/event.c b/src/notify/event.c
index 13733f0..757ec55 100644
--- a/src/notify/event.c
+++ b/src/notify/event.c
@@ -21,6 +21,7 @@
 #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>
 
@@ -28,6 +29,7 @@
 #include "event.h"
 #include "osd.h"
 
+
 static char * last_title = NULL, * last_message = NULL; /* pooled */
 
 static void clear (void)
@@ -38,28 +40,16 @@ static void clear (void)
     last_message = NULL;
 }
 
-static void reshow (void)
+static void update_button (void * unused, void * useless)
 {
-    if (! last_title || ! last_message)
-        return;
-
-    GdkPixbuf * pb = audgui_pixbuf_request_current ();
-    if (pb)
-        audgui_pixbuf_scale_within (& pb, 96);
-
-    osd_show (last_title, last_message, "audio-x-generic", pb);
-
-    if (pb)
-        g_object_unref (pb);
+    osd_update_button ();
 }
 
-static void update (void * unused, void * explicit)
+
+static void update (void * unused, void * useless)
 {
     if (! aud_drct_get_playing () || ! aud_drct_get_ready ())
     {
-        if (GPOINTER_TO_INT (explicit))
-            osd_show (_("Stopped"), _("Audacious is not playing."), NULL, NULL);
-
         return;
     }
 
@@ -86,7 +76,7 @@ static void update (void * unused, void * explicit)
     str_unref (album);
 
     /* pointer comparison works for pooled strings */
-    if (! GPOINTER_TO_INT (explicit) && title == last_title && message == last_message)
+    if (title == last_title && message == last_message)
     {
         str_unref (title);
         str_unref (message);
@@ -98,26 +88,63 @@ static void update (void * unused, void * explicit)
     str_unref (last_message);
     last_message = message;
 
-    reshow ();
+    char *coverfile = NULL;
+    char *filename = aud_playlist_entry_get_filename(list,entry);
+    const char *coverfileuri = aud_art_request_file(filename);
+
+    if (coverfileuri){
+        if(g_str_has_prefix (coverfileuri, "file://"))
+            coverfile = str_get (g_uri_unescape_string(coverfileuri + 7,""));
+        else
+            coverfile = str_get (g_uri_unescape_string(coverfileuri,""));
+        }
+    else{
+        GtkIconInfo * iconinfo = gtk_icon_theme_lookup_icon(gtk_icon_theme_get_default(),"audio-x-generic",512,GTK_ICON_LOOKUP_FORCE_SVG);
+        coverfile =  str_get (gtk_icon_info_get_filename(iconinfo));
+        gtk_icon_info_free(iconinfo);
+        }
+
+    osd_show (title, message, coverfile, FALSE);
+
+    if (filename)
+        str_unref (filename);
+    if (coverfile)
+        str_unref (coverfile);
+}
+
+static void update_explicit (void * unused, void * useless)
+{
+    if (! aud_drct_get_playing () || ! aud_drct_get_ready ())
+        osd_show (_("Stopped"), _("Audacious is not playing."), NULL, FALSE);
+    else
+        update(unused, useless);
+    return;
 }
 
 void event_init (void)
 {
-    update (NULL, GINT_TO_POINTER (FALSE));
-    hook_associate ("aosd toggle", (HookFunction) update, GINT_TO_POINTER (TRUE));
-    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 ("aosd toggle", (HookFunction) update_explicit, NULL);
+    hook_associate ("playback ready", (HookFunction) update, NULL);
+    hook_associate ("playlist update", (HookFunction) update, NULL);
+    hook_associate ("current art ready", (HookFunction) update, 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);
 }
 
 void event_uninit (void)
 {
-    hook_dissociate ("aosd toggle", (HookFunction) update);
+    hook_dissociate ("aosd toggle", (HookFunction) update_explicit);
     hook_dissociate ("playback ready", (HookFunction) update);
     hook_dissociate ("playlist update", (HookFunction) update);
-    hook_dissociate ("current art ready", (HookFunction) reshow);
+    hook_dissociate ("current art ready", (HookFunction) update);
+    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 c394bb3..6ec57a5 100644
--- a/src/notify/notify.c
+++ b/src/notify/notify.c
@@ -23,6 +23,8 @@
 #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"
@@ -47,12 +49,30 @@ 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)
+};
+
+
+
 AUD_GENERAL_PLUGIN
 (
     .name = N_("Desktop Notifications"),
     .domain = PACKAGE,
     .about_text = plugin_about,
     .init = plugin_init,
+    .prefs = & notify_prefs,
     .cleanup = plugin_cleanup
 )
 
@@ -60,24 +80,20 @@ short plugin_active = 0;
 
 gboolean plugin_init (void)
 {
-    AUDDBG("started!\n");
-    if(!osd_init()) {
-        AUDDBG("osd_init failed!\n");
-        return FALSE;
-    }
+    aud_config_set_defaults ("notify", notify_defaults);
+    osd_init();
     event_init();
-
     plugin_active = 1;
+    AUDDBG("Osd plugin initted\n");
     return TRUE;
 }
 
 
 void plugin_cleanup() {
     if(plugin_active) {
-        AUDDBG("started!\n");
         event_uninit();
         osd_uninit();
         plugin_active = 0;
-        AUDDBG("done!\n");
+        AUDDBG("Osd plugin uninitted\n");
     }
 }
diff --git a/src/notify/osd.c b/src/notify/osd.c
index 0dbf1c6..6bef53f 100644
--- a/src/notify/osd.c
+++ b/src/notify/osd.c
@@ -17,55 +17,169 @@
  * 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 NotifyNotification *notification = NULL;
+static gboolean actions_available = FALSE;
 
-bool_t osd_init()
-{
-    return notify_init ("Audacious");
+void osd_init() {
+    if (notify_is_initted())
+    {
+        AUDDBG("Notify is already initted, that shouldn't happen\n");
+        return;
+    }
+    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"));
+
+        GList *server_caps;
+        server_caps = notify_get_server_caps ();
+
+        if (g_list_find_custom (server_caps, "actions", (GCompareFunc)g_strcmp0))
+        {
+            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");
+                if (aud_get_bool ("notify", "actions") && actions_available)
+                    notify_notification_set_hint (notification, "resident", g_variant_new_boolean (TRUE));
+                else
+                    notify_notification_set_hint (notification, "resident", g_variant_new_boolean (FALSE));
+            }
+        else
+        {
+            AUDDBG("Notification server doesn't supports persistence\n");
+        }
+        g_list_free_full(server_caps, g_free);
+    }
 }
 
 void osd_uninit (void)
 {
     if (notification)
     {
+        GError *error = NULL;
+        if (notify_notification_close (notification, &error) == FALSE)
+            AUDDBG("%s!\n", error->message);
         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 gonext (NotifyNotification *notification,
+        const char *action,
+        gpointer user_data)
+{
+    aud_drct_pl_next();
+}
+
+void show_audacious (NotifyNotification *notification,
+        const char *action,
+        gpointer user_data)
+{
+    aud_interface_show(TRUE);
+}
+
+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){
+        GError *error = NULL;
+        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);
+        if(!notify_notification_show(notification, &error))
+            AUDDBG("Error “%s” when trying to send notification\n", error->message);
     }
 }
 
-void osd_show (const char * title, const char * _message, const char * icon,
- GdkPixbuf * pixbuf)
+
+void osd_show (const gchar * title, const gchar * _message, const gchar * coverfile, gboolean actiononly)
 {
-    char * message = g_markup_escape_text (_message, -1);
+    gchar * message = g_markup_escape_text (_message, -1);
+    GError *error = NULL;
 
-    if (pixbuf)
-        icon = NULL;
+    notify_notification_set_hint_string (notification, "image_path", coverfile);
 
-    if (notification)
-        notify_notification_update (notification, title, message, icon);
+    if (actions_available)
+    {
+        osd_update_button();
+    }
     else
     {
-        notification = notify_notification_new (title, message, icon);
-        g_signal_connect (notification, "closed", (GCallback) osd_closed_handler, NULL);
+        if (actiononly)
+        {
+            g_free (message);
+            return;
+        }
     }
 
-    if (pixbuf)
-        notify_notification_set_icon_from_pixbuf (notification, pixbuf);
+    if(!notify_notification_update(notification, title, message, "audacious"))
+         AUDDBG("Could not update osd!\n");
 
-    notify_notification_show (notification, NULL);
+    if(!notify_notification_show(notification, &error))
+        AUDDBG("Error “%s” when trying to send notification\n", error->message);
 
     g_free (message);
 }
diff --git a/src/notify/osd.h b/src/notify/osd.h
index dd7b82b..164ea4b 100644
--- a/src/notify/osd.h
+++ b/src/notify/osd.h
@@ -17,9 +17,7 @@
  * 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_init();
+void osd_uninit();
+void osd_show(const gchar *title, const gchar *message, const gchar *coverfile, gboolean actiononly);
+void osd_update_button(void);
