Project

General

Profile

notifyactionsupport.patch

Jean-Alexandre Anglès d'Auriac, May 22, 2013 16:53

View differences:

src/notify/event.c
2 2
 * event.c
3 3
 *
4 4
 * Copyright (C) 2010 Maximilian Bogner <max@mbogner.de>
5
 * Copyright (C) 2011-2013 John Lindgren and Jean-Alexandre Anglès d'Auriac
5
 * Copyright (C) 2011 John Lindgren <john.lindgren@tds.net>
6 6
 *
7 7
 * This program is free software; you can redistribute it and/or modify
8 8
 * it under the terms of the GNU General Public License as published by
......
18 18
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 19
 */
20 20

  
21
#include "event.h"
22

  
23 21
#include <audacious/drct.h>
24 22
#include <audacious/i18n.h>
25 23
#include <audacious/playlist.h>
......
27 25
#include <libaudcore/hook.h>
28 26
#include <libaudgui/libaudgui-gtk.h>
29 27

  
28
#include "config.h"
29
#include "event.h"
30 30
#include "osd.h"
31 31

  
32 32
static char * last_title = NULL, * last_message = NULL; /* pooled */
33
static GdkPixbuf * last_pixbuf = NULL;
34 33

  
35
static void clear_cache (void)
34
static void clear (void)
36 35
{
37 36
    str_unref (last_title);
38 37
    last_title = NULL;
39 38
    str_unref (last_message);
40 39
    last_message = NULL;
41

  
42
    if (last_pixbuf)
43
    {
44
        g_object_unref (last_pixbuf);
45
        last_pixbuf = NULL;
46
    }
47 40
}
48 41

  
49
static bool_t get_album_art (void)
42
static void update_button (void * unused, void * useless)
50 43
{
51
    if (last_pixbuf)
52
        return FALSE;
53

  
54
    last_pixbuf = audgui_pixbuf_request_current ();
55
    if (! last_pixbuf)
56
        return FALSE;
57

  
58
    audgui_pixbuf_scale_within (& last_pixbuf, 96);
59
    return TRUE;
44
    osd_refresh ();
60 45
}
61 46

  
62
static void show_stopped (void)
47
static void reshow (void)
63 48
{
64
    osd_show (_("Stopped"), _("Audacious is not playing."), "audacious", NULL);
65
}
49
    if (! last_title || ! last_message)
50
        return;
66 51

  
67
static void show_playing (void)
68
{
69
    if (last_title && last_message)
70
        osd_show (last_title, last_message, "audio-x-generic", last_pixbuf);
52
    GdkPixbuf * pb = audgui_pixbuf_request_current ();
53
    if (pb)
54
        audgui_pixbuf_scale_within (& pb, 96);
55

  
56
    osd_show (last_title, last_message, pb);
57

  
58
    if (pb)
59
        g_object_unref (pb);
71 60
}
72 61

  
73
static void playback_update (void)
62
static void update (void * unused, void * explicit)
74 63
{
75 64
    if (! aud_drct_get_playing () || ! aud_drct_get_ready ())
65
    {
66
        if (GPOINTER_TO_INT (explicit))
67
            osd_show (_("Stopped"), _("Audacious is not playing."), NULL);
68

  
76 69
        return;
70
    }
77 71

  
78 72
    int list = aud_playlist_get_playing ();
79 73
    int entry = aud_playlist_get_position (list);
......
98 92
    str_unref (album);
99 93

  
100 94
    /* pointer comparison works for pooled strings */
101
    if (title == last_title && message == last_message)
95
    if (! GPOINTER_TO_INT (explicit) && title == last_title && message == last_message)
102 96
    {
103 97
        str_unref (title);
104 98
        str_unref (message);
......
110 104
    str_unref (last_message);
111 105
    last_message = message;
112 106

  
113
    get_album_art ();
114
    show_playing ();
115
}
116

  
117
static void art_ready (void)
118
{
119
    if (aud_drct_get_playing () && get_album_art ())
120
        show_playing ();
121
}
122

  
123
static void playback_paused (void)
124
{
125
    if (aud_get_bool ("notify", "resident"))
126
        show_playing ();
127
}
128

  
129
static void playback_stopped (void)
130
{
131
    clear_cache ();
132

  
133
    if (aud_get_bool ("notify", "resident"))
134
        show_stopped ();
135
}
136

  
137
static void force_show (void)
138
{
139
    if (aud_drct_get_playing ())
140
        show_playing ();
141
    else
142
        show_stopped ();
107
    reshow ();
143 108
}
144 109

  
145 110
void event_init (void)
146 111
{
147
    if (aud_drct_get_playing ())
148
        playback_update ();
149
    else
150
        playback_stopped ();
151

  
152
    hook_associate ("playback begin", (HookFunction) clear_cache, NULL);
153
    hook_associate ("playback ready", (HookFunction) playback_update, NULL);
154
    hook_associate ("playlist update", (HookFunction) playback_update, NULL);
155
    hook_associate ("current art ready", (HookFunction) art_ready, NULL);
156
    hook_associate ("playback pause", (HookFunction) playback_paused, NULL);
157
    hook_associate ("playback unpause", (HookFunction) playback_paused, NULL);
158
    hook_associate ("playback stop", (HookFunction) playback_stopped, NULL);
159

  
160
    hook_associate ("aosd toggle", (HookFunction) force_show, NULL);
112
    update (NULL, GINT_TO_POINTER (FALSE));
113
    hook_associate ("aosd toggle", (HookFunction) update, GINT_TO_POINTER (TRUE));
114
    hook_associate ("playback ready", (HookFunction) update, GINT_TO_POINTER (FALSE));
115
    hook_associate ("playlist update", (HookFunction) update, GINT_TO_POINTER (FALSE));
116
    hook_associate ("current art ready", (HookFunction) reshow, NULL);
117
    hook_associate ("playback pause", (HookFunction) update_button, NULL);
118
    hook_associate ("playback unpause", (HookFunction) update_button, NULL);
119
    hook_associate ("playback begin", (HookFunction) update_button, NULL);
120
    hook_associate ("playback stop", (HookFunction) update_button, NULL);
121
    hook_associate ("playback begin", (HookFunction) clear, NULL);
122
    hook_associate ("playback stop", (HookFunction) clear, NULL);
161 123
}
162 124

  
163 125
void event_uninit (void)
164 126
{
165
    hook_dissociate ("playback begin", (HookFunction) clear_cache);
166
    hook_dissociate ("playback ready", (HookFunction) playback_update);
167
    hook_dissociate ("playlist update", (HookFunction) playback_update);
168
    hook_dissociate ("current art ready", (HookFunction) art_ready);
169
    hook_dissociate ("playback pause", (HookFunction) playback_paused);
170
    hook_dissociate ("playback unpause", (HookFunction) playback_paused);
171
    hook_dissociate ("playback stop", (HookFunction) playback_stopped);
172

  
173
    hook_dissociate ("aosd toggle", (HookFunction) force_show);
174

  
175
    clear_cache ();
176
    osd_hide ();
127
    hook_dissociate ("aosd toggle", (HookFunction) update);
128
    hook_dissociate ("playback ready", (HookFunction) update);
129
    hook_dissociate ("playlist update", (HookFunction) update);
130
    hook_dissociate ("current art ready", (HookFunction) reshow);
131
    hook_dissociate ("playback pause", (HookFunction) update_button);
132
    hook_dissociate ("playback unpause", (HookFunction) update_button);
133
    hook_dissociate ("playback begin", (HookFunction) update_button);
134
    hook_dissociate ("playback stop", (HookFunction) update_button);
135
    hook_dissociate ("playback begin", (HookFunction) clear);
136
    hook_dissociate ("playback stop", (HookFunction) clear);
137
    clear ();
177 138
}
src/notify/notify.c
2 2
 * notify.c
3 3
 *
4 4
 * Copyright (C) 2010 Maximilian Bogner <max@mbogner.de>
5
 * Copyright (C) 2013 John Lindgren and Jean-Alexandre Anglès d'Auriac
6 5
 *
7 6
 * This program is free software; you can redistribute it and/or modify
8 7
 * it under the terms of the GNU General Public License as published by
......
18 17
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 18
 */
20 19

  
20
#include <glib.h>
21 21
#include <gtk/gtk.h>
22 22

  
23
#include <libnotify/notify.h>
24

  
25 23
#include <audacious/i18n.h>
26 24
#include <audacious/plugin.h>
25
#include <audacious/debug.h>
27 26
#include <audacious/preferences.h>
28 27
#include <audacious/misc.h>
29 28

  
29
#include "config.h"
30 30
#include "event.h"
31
#include "osd.h"
32

  
33
gboolean plugin_init (void);
34
void plugin_cleanup (void);
31 35

  
32 36
static const char plugin_about[] =
33
 N_("Desktop Notifications Plugin for Audacious\n"
37
 N_("Based on libnotify-aosd by Maximilian Bogner:\n"
38
    "http://www.mbogner.de/projects/libnotify-aosd/\n\n"
34 39
    "Copyright (C) 2010 Maximilian Bogner\n"
35
    "Copyright (C) 2011-2013 John Lindgren and Jean-Alexandre Anglès d'Auriac\n\n"
40
    "Copyright (C) 2011 John Lindgren\n\n"
36 41
    "This plugin is free software: you can redistribute it and/or modify "
37 42
    "it under the terms of the GNU General Public License as published by "
38 43
    "the Free Software Foundation, either version 3 of the License, or "
......
46 51

  
47 52
static const char * const notify_defaults[] = {
48 53
 "actions", "TRUE",
49
 "resident", "FALSE",
50
 NULL
51
};
52

  
53
static bool_t plugin_init (void)
54
{
55
    aud_config_set_defaults ("notify", notify_defaults);
56

  
57
    if (! notify_init ("Audacious"))
58
        return FALSE;
54
 NULL};
59 55

  
60
    event_init();
61
    return TRUE;
62
}
63

  
64
static void plugin_cleanup (void)
65
{
66
    event_uninit ();
67
    notify_uninit ();
68
}
69 56

  
70
static void plugin_reinit (void)
71
{
72
    event_uninit ();
73
    event_init ();
74
}
75

  
76
static const PreferencesWidget prefs_widgets[] = {
77
 {WIDGET_CHK_BTN, N_("Show playback controls"),
78
  .cfg_type = VALUE_BOOLEAN, .csect = "notify", .cname = "actions",
79
  .callback = plugin_reinit},
80
 {WIDGET_CHK_BTN, N_("Always show notification"),
81
  .cfg_type = VALUE_BOOLEAN, .csect = "notify", .cname = "resident",
82
  .callback = plugin_reinit}
57
static const PreferencesWidget notify_widgets[] = {
58
 {WIDGET_CHK_BTN, N_("Activate controls inside of the notification"),
59
 .cfg_type = VALUE_BOOLEAN, .csect = "notify", .cname = "actions"},
83 60
};
84 61

  
85
static const PluginPreferences plugin_prefs = {
86
 .widgets = prefs_widgets,
87
 .n_widgets = G_N_ELEMENTS (prefs_widgets)
62
static const PluginPreferences notify_prefs = {
63
 .widgets = notify_widgets,
64
 .n_widgets = G_N_ELEMENTS (notify_widgets),
65
 .apply = toggleaction
88 66
};
89 67

  
68

  
69

  
90 70
AUD_GENERAL_PLUGIN
91 71
(
92 72
    .name = N_("Desktop Notifications"),
93 73
    .domain = PACKAGE,
94 74
    .about_text = plugin_about,
95
    .prefs = & plugin_prefs,
96 75
    .init = plugin_init,
76
    .prefs = & notify_prefs,
97 77
    .cleanup = plugin_cleanup
98 78
)
79

  
80
short plugin_active = 0;
81

  
82
gboolean plugin_init (void)
83
{
84
    AUDDBG("started!\n");
85
    aud_config_set_defaults ("notify", notify_defaults);
86
    if(!osd_init()) {
87
        AUDDBG("osd_init failed!\n");
88
        return FALSE;
89
    }
90
    event_init();
91

  
92
    plugin_active = 1;
93
    AUDDBG("Osd plugin initted\n");
94
    return TRUE;
95
}
96

  
97

  
98
void plugin_cleanup() {
99
    if(plugin_active) {
100
        AUDDBG("started!\n");
101
        event_uninit();
102
        osd_uninit();
103
        plugin_active = 0;
104
        AUDDBG("done!\n");
105
    }
106
}
src/notify/osd.c
2 2
 * osd.c
3 3
 *
4 4
 * Copyright (C) 2010 Maximilian Bogner <max@mbogner.de>
5
 * Copyright (C) 2013 John Lindgren and Jean-Alexandre Anglès d'Auriac
6 5
 *
7 6
 * This program is free software; you can redistribute it and/or modify
8 7
 * it under the terms of the GNU General Public License as published by
......
18 17
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 18
 */
20 19

  
21
#include "osd.h"
22

  
23
#include <libnotify/notify.h>
24

  
20
#include <libaudcore/core.h>
21
#include <libaudcore/hook.h>
22
#include <audacious/debug.h>
25 23
#include <audacious/i18n.h>
26 24
#include <audacious/drct.h>
27 25
#include <audacious/misc.h>
26
#include <libnotify/notify.h>
27
#include "osd.h"
28 28

  
29
static void show_cb (void)
29
static NotifyNotification * notification = NULL;
30
static gboolean actions_available = FALSE;
31
static gboolean resident_notification = FALSE;
32

  
33

  
34

  
35
bool_t osd_init()
30 36
{
31
    aud_interface_show (TRUE);
37
    if (notify_is_initted())
38
    {
39
        AUDDBG("Notify is already initted, that shouldn't happen\n");
40
        return FALSE;
41
    }
42
    if (notify_init("Audacious"))
43
    {
44
        notification = notify_notification_new("Notification", NULL, NULL);
45

  
46
        notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
47
        notify_notification_set_hint (notification, "desktop-entry", g_variant_new_string ("audacious"));
48
        notify_notification_set_category (notification, "x-gnome.music");
49

  
50
        GList *server_caps;
51
        server_caps = notify_get_server_caps ();
52

  
53
        if (g_list_find_custom (server_caps, "actions", (GCompareFunc)g_strcmp0) && aud_get_bool ("notify", "actions"))
54
        {
55
            actions_available = TRUE;
56
            if (g_list_find_custom (server_caps, "action-icons", (GCompareFunc)g_strcmp0))
57
                notify_notification_set_hint (notification, "action-icons", g_variant_new_boolean (TRUE));
58
            if (g_list_find_custom (server_caps, "persistence", (GCompareFunc)g_strcmp0) )
59
            {
60
                AUDDBG("Notification server supports persistence\n");
61
                resident_notification = TRUE;
62
                notify_notification_set_hint (notification, "resident", g_variant_new_boolean (TRUE));
63
                notify_notification_set_hint (notification, "transient", g_variant_new_boolean (FALSE));
64
            }
65
        }
66
        else
67
        {
68
            notify_notification_set_hint (notification, "resident", g_variant_new_boolean (FALSE));
69
            notify_notification_set_hint (notification, "transient", g_variant_new_boolean (TRUE));
70
        }
71
        g_list_free_full(server_caps, g_free);
72
        return TRUE;
73
    }
74
    else 
75
        return FALSE;
32 76
}
33 77

  
34
static void osd_setup (NotifyNotification *notification)
78
void osd_uninit (void)
35 79
{
36
    bool_t resident = aud_get_bool ("notify", "resident");
80
    if (notification)
81
    {
82
        GError *error = NULL;
83
        if (notify_notification_close (notification, &error) == FALSE)
84
            AUDDBG("%s!\n", error->message);
85
        if(error)
86
            g_error_free(error);
87
        g_object_unref (notification);
88
        notification = NULL;
89
    }
37 90

  
38
    notify_notification_set_hint (notification, "desktop-entry",
39
     g_variant_new_string ("audacious"));
91
    notify_uninit();
92
    AUDDBG("Notify uninitted\n");
93
}
40 94

  
41
    notify_notification_set_hint (notification, "action-icons", g_variant_new_boolean (TRUE));
42
    notify_notification_set_hint (notification, "resident", g_variant_new_boolean (resident));
43
    notify_notification_set_hint (notification, "transient", g_variant_new_boolean (! resident));
44 95

  
45
    notify_notification_set_urgency (notification, NOTIFY_URGENCY_LOW);
46
    notify_notification_set_timeout (notification, resident ?
47
     NOTIFY_EXPIRES_NEVER : NOTIFY_EXPIRES_DEFAULT);
96
void goprevious (NotifyNotification *notification,
97
            const char *action,
98
            gpointer user_data)
99
{
100
    aud_drct_pl_prev();
48 101
}
49 102

  
50
void osd_setup_buttons (NotifyNotification *notification)
103
void gonext (NotifyNotification *notification,
104
        const char *action,
105
        gpointer user_data)
51 106
{
52
    notify_notification_clear_actions (notification);
53

  
54
    if (! aud_get_bool ("notify", "actions"))
55
        return;
56

  
57
    notify_notification_add_action (notification, "default", _("Show"),
58
     NOTIFY_ACTION_CALLBACK (show_cb), NULL, NULL);
107
    aud_drct_pl_next();
108
}
59 109

  
60
    bool_t playing = aud_drct_get_playing ();
61
    bool_t paused = aud_drct_get_paused ();
110
void show_audacious (NotifyNotification *notification,
111
        const char *action,
112
        gpointer user_data)
113
{
114
    aud_interface_show(TRUE);
115
}
62 116

  
63
    if (playing && ! paused)
64
        notify_notification_add_action (notification, "media-playback-pause",
65
         _("Pause"), NOTIFY_ACTION_CALLBACK (aud_drct_pause), NULL, NULL);
117
void playpause (NotifyNotification *notification,
118
           const char *action,
119
           gpointer user_data)
120
{
121
    if(aud_drct_get_playing())
122
    {aud_drct_pause();}
66 123
    else
67
        notify_notification_add_action (notification, "media-playback-start",
68
         _("Play"), NOTIFY_ACTION_CALLBACK (aud_drct_play), NULL, NULL);
124
    {aud_drct_play();}
125
}
69 126

  
70
    if (playing)
71
        notify_notification_add_action (notification, "media-skip-forward",
72
         _("Next"), NOTIFY_ACTION_CALLBACK (aud_drct_pl_next), NULL, NULL);
127
void osd_update_button(void){
128
    if(actions_available){
129
        gboolean paused = TRUE;
130
        if (aud_drct_get_playing()) {paused = aud_drct_get_paused();}
131

  
132
        notify_notification_clear_actions (notification);
133

  
134
        notify_notification_add_action (notification,
135
                    "media-skip-backward",
136
                    N_("Previous"),
137
                    NOTIFY_ACTION_CALLBACK(goprevious),
138
                    NULL,
139
                    NULL);
140

  
141
        notify_notification_add_action (notification,
142
                    paused ? "media-playback-start" : "media-playback-pause",
143
                    paused ? N_("Play") : N_("Pause"),
144
                    NOTIFY_ACTION_CALLBACK(playpause),
145
                    NULL,
146
                    NULL);
147

  
148
        notify_notification_add_action (notification,
149
                    "media-skip-forward",
150
                    N_("Next"),
151
                    NOTIFY_ACTION_CALLBACK(gonext),
152
                    NULL,
153
                    NULL);
154

  
155
        notify_notification_add_action (notification,
156
                    "default",
157
                    N_("Show Audacious"),
158
                    NOTIFY_ACTION_CALLBACK(show_audacious),
159
                    NULL,
160
                    NULL);
161
    }
73 162
}
74 163

  
75
static NotifyNotification * notification = NULL;
164
void osd_refresh(void){
165
    osd_update_button();
166
    if(resident_notification)
167
    {
168
        GError *error = NULL;
169
        if(!notify_notification_show(notification, &error))
170
            AUDDBG("Error “%s” when trying to send notification\n", error->message);
171
        if(error)
172
            g_error_free(error);
173
    }
174
}
76 175

  
77
void osd_show (const char * title, const char * _message, const char * icon,
78
 GdkPixbuf * pixbuf)
176
void osd_show (const gchar * title, const gchar * _message, GdkPixbuf *cover)
79 177
{
80
    char * message = g_markup_escape_text (_message, -1);
178
    gchar * message = g_markup_escape_text (_message, -1);
179
    GError *error = NULL;
81 180

  
82
    if (pixbuf)
83
        icon = NULL;
181
    if(cover)
182
        notify_notification_set_image_from_pixbuf(notification, cover);
84 183

  
85
    if (notification)
86
        notify_notification_update (notification, title, message, icon);
87
    else
88
    {
89
        notification = notify_notification_new (title, message, icon);
90
        osd_setup (notification);
91
    }
184
    osd_update_button();
92 185

  
93
    if (pixbuf)
94
        notify_notification_set_image_from_pixbuf (notification, pixbuf);
186
    if(!notify_notification_update(notification, title, message, "audacious"))
187
         AUDDBG("Could not update osd!\n");
95 188

  
96
    osd_setup_buttons (notification);
97
    notify_notification_show (notification, NULL);
189
    if(!notify_notification_show(notification, &error))
190
        AUDDBG("Error “%s” when trying to send notification\n", error->message);
191
    if(error)
192
        g_error_free(error);
98 193

  
99 194
    g_free (message);
100 195
}
101 196

  
102
void osd_hide (void)
103
{
104
    if (! notification)
105
        return;
197
void toggleaction(){
198
    GList *server_caps;
199
    server_caps = notify_get_server_caps ();
106 200

  
107
    notify_notification_close (notification, NULL);
108
    g_object_unref (notification);
109
    notification = NULL;
201
    if (g_list_find_custom (server_caps, "actions", (GCompareFunc)g_strcmp0) && aud_get_bool ("notify", "actions"))
202
    {
203
        actions_available = TRUE;
204
        if (g_list_find_custom (server_caps, "action-icons", (GCompareFunc)g_strcmp0))
205
            notify_notification_set_hint (notification, "action-icons", g_variant_new_boolean (TRUE));
206
        if (g_list_find_custom (server_caps, "persistence", (GCompareFunc)g_strcmp0) )
207
        {
208
            AUDDBG("Notification server supports persistence\n");
209
            resident_notification = TRUE;
210
            notify_notification_set_hint (notification, "resident", g_variant_new_boolean (TRUE));
211
            notify_notification_set_hint (notification, "transient", g_variant_new_boolean (FALSE));
212
            osd_update_button();
213
            notify_notification_show(notification, NULL);
214
        }
215
    }
216
    else
217
    {
218
        actions_available = FALSE;
219
        resident_notification = FALSE;
220
        notify_notification_clear_actions (notification);
221
        notify_notification_set_hint (notification, "resident", g_variant_new_boolean (FALSE));
222
        notify_notification_set_hint (notification, "transient", g_variant_new_boolean (TRUE));
223
        notify_notification_close (notification, NULL);
224
    }
110 225
}
src/notify/osd.h
17 17
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 18
 */
19 19

  
20
#include <gdk-pixbuf/gdk-pixbuf.h>
21

  
22
void osd_show (const char * title, const char * message, const char * icon, GdkPixbuf * pixbuf);
23
void osd_hide (void);
20
bool_t osd_init (void);
21
void osd_uninit (void);
22
void osd_show (const gchar *title, const gchar *message, GdkPixbuf *pixbuf);
23
void osd_refresh (void);
24
void toggleaction (void);