2 * This file Copyright (C) Mnemosyne LLC
4 * This file is licensed by the GPL version 2. Works owned by the
5 * Transmission project are granted a special exemption to clause 2(b)
6 * so that the bulk of its code can remain under the MIT license.
7 * This exemption does not extend to derived works not owned by
8 * the Transmission project.
10 * $Id: notify.c 13265 2012-04-07 00:30:37Z jordan $
13 #include <string.h> /* strcmp() */
17 #include <glib/gi18n.h>
23 #define NOTIFICATIONS_DBUS_NAME "org.freedesktop.Notifications"
24 #define NOTIFICATIONS_DBUS_CORE_OBJECT "/org/freedesktop/Notifications"
25 #define NOTIFICATIONS_DBUS_CORE_INTERFACE "org.freedesktop.Notifications"
27 static GDBusProxy
*proxy
= NULL
;
28 static GHashTable
*active_notifications
= NULL
;
29 static gboolean server_supports_actions
= FALSE
;
31 typedef struct _TrNotification
39 tr_notification_free( gpointer data
)
41 TrNotification
* n
= data
;
43 g_object_unref( G_OBJECT( n
->core
) );
48 get_capabilities_callback( GObject
* source
,
50 gpointer user_data UNUSED
)
56 result
= g_dbus_proxy_call_finish( G_DBUS_PROXY( source
), res
, NULL
);
57 if( !result
|| !g_variant_is_of_type( result
, G_VARIANT_TYPE( "(as)" ) ) )
60 g_variant_unref( result
);
64 g_variant_get( result
, "(^a&s)", &caps
);
65 for( i
= 0; caps
[i
]; i
++ )
67 if( strcmp( caps
[i
], "actions" ) == 0 )
69 server_supports_actions
= TRUE
;
74 g_variant_unref( result
);
78 g_signal_callback( GDBusProxy
* proxy UNUSED
,
79 char * sender_name UNUSED
,
82 gpointer user_data UNUSED
)
87 g_return_if_fail( g_variant_is_of_type( params
, G_VARIANT_TYPE( "(u*)" ) ) );
89 g_variant_get( params
, "(u*)", &id
, NULL
);
90 n
= g_hash_table_lookup( active_notifications
,
91 GINT_TO_POINTER( (int *) &id
) );
95 if( strcmp( signal_name
, "NotificationClosed" ) == 0 )
97 g_hash_table_remove( active_notifications
,
98 GINT_TO_POINTER( (int *) &n
->id
) );
100 else if( strcmp( signal_name
, "ActionInvoked" ) == 0 &&
101 g_variant_is_of_type( params
, G_VARIANT_TYPE( "(us)" ) ) )
106 tor
= gtr_core_find_torrent( n
->core
, n
->torrent_id
);
110 g_variant_get( params
, "(u&s)", NULL
, &action
);
111 if( strcmp( action
, "folder" ) == 0 )
113 gtr_core_open_folder( n
->core
, n
->torrent_id
);
115 else if( strcmp( action
, "file" ) == 0)
117 const tr_info
* inf
= tr_torrentInfo( tor
);
118 const char * dir
= tr_torrentGetDownloadDir( tor
);
119 char * path
= g_build_filename( dir
, inf
->files
[0].name
, NULL
);
120 gtr_open_file( path
);
127 dbus_proxy_ready_callback( GObject
* source UNUSED
,
129 gpointer user_data UNUSED
)
131 proxy
= g_dbus_proxy_new_for_bus_finish( res
, NULL
);
134 g_warning( "Failed to create proxy for %s", NOTIFICATIONS_DBUS_NAME
);
138 g_signal_connect( proxy
, "g-signal",
139 G_CALLBACK( g_signal_callback
), NULL
);
140 g_dbus_proxy_call( proxy
,
142 g_variant_new( "()" ),
143 G_DBUS_CALL_FLAGS_NONE
, -1, NULL
,
144 get_capabilities_callback
, NULL
);
148 gtr_notify_init( void )
150 active_notifications
= g_hash_table_new_full( g_int_hash
, g_int_equal
,
151 NULL
, tr_notification_free
);
152 g_dbus_proxy_new_for_bus( G_BUS_TYPE_SESSION
,
153 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
,
155 NOTIFICATIONS_DBUS_NAME
,
156 NOTIFICATIONS_DBUS_CORE_OBJECT
,
157 NOTIFICATIONS_DBUS_CORE_INTERFACE
,
158 NULL
, dbus_proxy_ready_callback
, NULL
);
162 notify_callback( GObject
* source
,
166 TrNotification
* n
= user_data
;
169 result
= g_dbus_proxy_call_finish( G_DBUS_PROXY( source
), res
, NULL
);
170 if( !result
|| !g_variant_is_of_type( result
, G_VARIANT_TYPE( "(u)" ) ) )
173 g_variant_unref( result
);
174 tr_notification_free( n
);
178 g_variant_get( result
, "(u)", &n
->id
);
179 g_hash_table_insert( active_notifications
,
180 GINT_TO_POINTER( ( int * )&n
->id
), n
);
182 g_variant_unref( result
);
186 gtr_notify_torrent_completed( TrCore
* core
, int torrent_id
)
188 GVariantBuilder actions_builder
;
191 const char * cmd
= gtr_pref_string_get( PREF_KEY_TORRENT_COMPLETE_SOUND_COMMAND
);
193 if( gtr_pref_flag_get( PREF_KEY_TORRENT_COMPLETE_SOUND_ENABLED
) )
194 g_spawn_command_line_async( cmd
, NULL
);
196 if( ! gtr_pref_flag_get( PREF_KEY_TORRENT_COMPLETE_NOTIFICATION_ENABLED
) )
199 g_return_if_fail( G_IS_DBUS_PROXY( proxy
) );
201 tor
= gtr_core_find_torrent( core
, torrent_id
);
203 n
= g_new0( TrNotification
, 1 );
204 n
->core
= g_object_ref( G_OBJECT( core
) );
205 n
->torrent_id
= torrent_id
;
207 g_variant_builder_init( &actions_builder
, G_VARIANT_TYPE( "as" ) );
209 if( server_supports_actions
)
211 const tr_info
* inf
= tr_torrentInfo( tor
);
212 if( inf
->fileCount
== 1 )
214 g_variant_builder_add( &actions_builder
, "s", "file" );
215 g_variant_builder_add( &actions_builder
, "s", _( "Open File" ) );
219 g_variant_builder_add( &actions_builder
, "s", "folder" );
220 g_variant_builder_add( &actions_builder
, "s", _( "Open Folder" ) );
224 g_dbus_proxy_call( proxy
,
226 g_variant_new( "(susssasa{sv}i)",
227 "Transmission", n
->id
, "transmission",
228 _( "Torrent Complete" ),
229 tr_torrentName( tor
),
230 &actions_builder
, NULL
, -1 ),
231 G_DBUS_CALL_FLAGS_NONE
, -1, NULL
,
232 notify_callback
, n
);
236 gtr_notify_torrent_added( const char * name
)
240 g_return_if_fail( G_IS_DBUS_PROXY( proxy
) );
242 if( !gtr_pref_flag_get( PREF_KEY_TORRENT_ADDED_NOTIFICATION_ENABLED
) )
245 n
= g_new0( TrNotification
, 1 );
246 g_dbus_proxy_call( proxy
,
248 g_variant_new( "(susssasa{sv}i)",
249 "Transmission", 0, "transmission",
250 _( "Torrent Added" ), name
,
252 G_DBUS_CALL_FLAGS_NONE
, -1, NULL
,
253 notify_callback
, n
);