(trunk libT) #4372 "make notification and system sounds configurable" -- instead of using notify-send, use GDBus on the org.freedesktop.Notifications API. Patch by fmuellner.
This commit is contained in:
parent
4e2b6f6e9f
commit
d524deecb0
|
@ -93,9 +93,7 @@ tr_prefs_init_defaults( tr_benc * d )
|
|||
tr_bencDictAddBool( d, PREF_KEY_SHOW_BACKUP_TRACKERS, FALSE );
|
||||
tr_bencDictAddStr ( d, PREF_KEY_STATUSBAR_STATS, "total-ratio" );
|
||||
|
||||
tr_bencDictAddStr ( d, PREF_KEY_TORRENT_ADDED_NOTIFICATION_COMMAND, "notify-send -c transfer -i transmission '%s' '%s'" );
|
||||
tr_bencDictAddBool( d, PREF_KEY_TORRENT_ADDED_NOTIFICATION_ENABLED, true );
|
||||
tr_bencDictAddStr ( d, PREF_KEY_TORRENT_COMPLETE_NOTIFICATION_COMMAND, "notify-send -c transfer.complete -i transmission '%s' '%s'" );
|
||||
tr_bencDictAddBool( d, PREF_KEY_TORRENT_COMPLETE_NOTIFICATION_ENABLED, true );
|
||||
tr_bencDictAddStr ( d, PREF_KEY_TORRENT_COMPLETE_SOUND_COMMAND, "canberra-gtk-play -i complete-download -d 'transmission torrent downloaded'" );
|
||||
tr_bencDictAddBool( d, PREF_KEY_TORRENT_COMPLETE_SOUND_ENABLED, true );
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "hig.h"
|
||||
#include "makemeta-ui.h"
|
||||
#include "msgwin.h"
|
||||
#include "notify.h"
|
||||
#include "open-dialog.h"
|
||||
#include "relocate.h"
|
||||
#include "stats.h"
|
||||
|
@ -643,6 +644,9 @@ main( int argc, char ** argv )
|
|||
gtr_pref_init( cbdata.config_dir );
|
||||
g_mkdir_with_parents( cbdata.config_dir, 0755 );
|
||||
|
||||
/* init notifications */
|
||||
gtr_notify_init( );
|
||||
|
||||
/* init the application for the specified config dir */
|
||||
stat( cbdata.config_dir, &sb );
|
||||
application_id = g_strdup_printf( "com.transmissionbt.transmission_%lu_%lu", (unsigned long)sb.st_dev, (unsigned long)sb.st_ino );
|
||||
|
|
239
gtk/notify.c
239
gtk/notify.c
|
@ -10,38 +10,243 @@
|
|||
* $Id$
|
||||
*/
|
||||
|
||||
#include <string.h> /* strcmp() */
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include "conf.h"
|
||||
#include "notify.h"
|
||||
#include "tr-prefs.h"
|
||||
#include "util.h"
|
||||
|
||||
#define NOTIFICATIONS_DBUS_NAME "org.freedesktop.Notifications"
|
||||
#define NOTIFICATIONS_DBUS_CORE_OBJECT "/org/freedesktop/Notifications"
|
||||
#define NOTIFICATIONS_DBUS_CORE_INTERFACE "org.freedesktop.Notifications"
|
||||
|
||||
static GDBusProxy *proxy = NULL;
|
||||
static GHashTable *active_notifications = NULL;
|
||||
static gboolean server_supports_actions = FALSE;
|
||||
|
||||
typedef struct _TrNotification
|
||||
{
|
||||
guint id;
|
||||
TrCore * core;
|
||||
int torrent_id;
|
||||
} TrNotification;
|
||||
|
||||
static void
|
||||
tr_notification_free( gpointer data )
|
||||
{
|
||||
TrNotification * n = data;
|
||||
if( n->core )
|
||||
g_object_unref( G_OBJECT( n->core ) );
|
||||
g_free( n );
|
||||
}
|
||||
|
||||
static void
|
||||
get_capabilities_callback( GObject * source,
|
||||
GAsyncResult * res,
|
||||
gpointer user_data UNUSED )
|
||||
{
|
||||
GVariant *result;
|
||||
char **caps;
|
||||
int i;
|
||||
|
||||
result = g_dbus_proxy_call_finish( G_DBUS_PROXY( source ), res, NULL );
|
||||
if( !result || !g_variant_is_of_type( result, G_VARIANT_TYPE( "(as)" ) ) )
|
||||
{
|
||||
if( result )
|
||||
g_variant_unref( result );
|
||||
return;
|
||||
}
|
||||
|
||||
g_variant_get( result, "(^a&s)", &caps );
|
||||
for( i = 0; caps[i]; i++ )
|
||||
{
|
||||
if( strcmp( caps[i], "actions" ) == 0 )
|
||||
{
|
||||
server_supports_actions = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_free( caps );
|
||||
g_variant_unref( result );
|
||||
}
|
||||
|
||||
static void
|
||||
g_signal_callback( GDBusProxy * proxy UNUSED,
|
||||
char * sender_name UNUSED,
|
||||
char * signal_name,
|
||||
GVariant * params,
|
||||
gpointer user_data UNUSED )
|
||||
{
|
||||
TrNotification * n;
|
||||
guint id;
|
||||
|
||||
g_return_if_fail( g_variant_is_of_type( params, G_VARIANT_TYPE( "(u*)" ) ) );
|
||||
|
||||
g_variant_get( params, "(u*)", &id, NULL );
|
||||
n = g_hash_table_lookup( active_notifications,
|
||||
GINT_TO_POINTER( (int *) &id ) );
|
||||
if( n == NULL )
|
||||
return;
|
||||
|
||||
if( strcmp( signal_name, "NotificationClosed" ) == 0 )
|
||||
{
|
||||
g_hash_table_remove( active_notifications,
|
||||
GINT_TO_POINTER( (int *) &n->id ) );
|
||||
}
|
||||
else if( strcmp( signal_name, "ActionInvoked" ) == 0 &&
|
||||
g_variant_is_of_type( params, G_VARIANT_TYPE( "(us)" ) ) )
|
||||
{
|
||||
char * action;
|
||||
tr_torrent * tor;
|
||||
|
||||
tor = gtr_core_find_torrent( n->core, n->torrent_id );
|
||||
if( tor == NULL )
|
||||
return;
|
||||
|
||||
g_variant_get( params, "(u&s)", NULL, &action );
|
||||
if( strcmp( action, "folder" ) == 0 )
|
||||
{
|
||||
gtr_core_open_folder( n->core, n->torrent_id );
|
||||
}
|
||||
else if( strcmp( action, "file" ) == 0)
|
||||
{
|
||||
const tr_info * inf = tr_torrentInfo( tor );
|
||||
const char * dir = tr_torrentGetDownloadDir( tor );
|
||||
char * path = g_build_filename( dir, inf->files[0].name, NULL );
|
||||
gtr_open_file( path );
|
||||
g_free( path );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dbus_proxy_ready_callback( GObject * source UNUSED,
|
||||
GAsyncResult * res,
|
||||
gpointer user_data UNUSED )
|
||||
{
|
||||
proxy = g_dbus_proxy_new_for_bus_finish( res, NULL );
|
||||
if( proxy == NULL )
|
||||
{
|
||||
g_warning( "Failed to create proxy for %s", NOTIFICATIONS_DBUS_NAME );
|
||||
return;
|
||||
}
|
||||
|
||||
g_signal_connect( proxy, "g-signal",
|
||||
G_CALLBACK( g_signal_callback ), NULL );
|
||||
g_dbus_proxy_call( proxy,
|
||||
"GetCapabilities",
|
||||
g_variant_new( "()" ),
|
||||
G_DBUS_CALL_FLAGS_NONE, -1, NULL,
|
||||
get_capabilities_callback, NULL );
|
||||
}
|
||||
|
||||
void
|
||||
gtr_notify_init( void )
|
||||
{
|
||||
active_notifications = g_hash_table_new_full( g_int_hash, g_int_equal,
|
||||
NULL, tr_notification_free );
|
||||
g_dbus_proxy_new_for_bus( G_BUS_TYPE_SESSION,
|
||||
G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
|
||||
NULL,
|
||||
NOTIFICATIONS_DBUS_NAME,
|
||||
NOTIFICATIONS_DBUS_CORE_OBJECT,
|
||||
NOTIFICATIONS_DBUS_CORE_INTERFACE,
|
||||
NULL, dbus_proxy_ready_callback, NULL );
|
||||
}
|
||||
|
||||
static void
|
||||
notify_callback( GObject * source,
|
||||
GAsyncResult * res,
|
||||
gpointer user_data )
|
||||
{
|
||||
TrNotification * n = user_data;
|
||||
GVariant * result;
|
||||
|
||||
result = g_dbus_proxy_call_finish( G_DBUS_PROXY( source ), res, NULL );
|
||||
if( !result || !g_variant_is_of_type( result, G_VARIANT_TYPE( "(u)" ) ) )
|
||||
{
|
||||
if( result )
|
||||
g_variant_unref( result );
|
||||
tr_notification_free( n );
|
||||
return;
|
||||
}
|
||||
|
||||
g_variant_get( result, "(u)", &n->id );
|
||||
g_hash_table_insert( active_notifications,
|
||||
GINT_TO_POINTER( ( int * )&n->id ), n );
|
||||
|
||||
g_variant_unref( result );
|
||||
}
|
||||
|
||||
void
|
||||
gtr_notify_torrent_completed( TrCore * core, int torrent_id )
|
||||
{
|
||||
if( gtr_pref_flag_get( PREF_KEY_TORRENT_COMPLETE_SOUND_ENABLED ) )
|
||||
{
|
||||
GVariantBuilder actions_builder;
|
||||
TrNotification * n;
|
||||
tr_torrent * tor;
|
||||
const char * cmd = gtr_pref_string_get( PREF_KEY_TORRENT_COMPLETE_SOUND_COMMAND );
|
||||
g_spawn_command_line_async( cmd, NULL );
|
||||
|
||||
if( ! gtr_pref_flag_get( PREF_KEY_TORRENT_COMPLETE_NOTIFICATION_ENABLED ) )
|
||||
return;
|
||||
|
||||
g_return_if_fail( G_IS_DBUS_PROXY( proxy ) );
|
||||
|
||||
tor = gtr_core_find_torrent( core, torrent_id );
|
||||
|
||||
n = g_new0( TrNotification, 1 );
|
||||
n->core = g_object_ref( G_OBJECT( core ) );
|
||||
n->torrent_id = torrent_id;
|
||||
|
||||
g_variant_builder_init( &actions_builder, G_VARIANT_TYPE( "as" ) );
|
||||
|
||||
if( server_supports_actions )
|
||||
{
|
||||
const tr_info * inf = tr_torrentInfo( tor );
|
||||
if( inf->fileCount == 1 )
|
||||
{
|
||||
g_variant_builder_add( &actions_builder, "s", "file" );
|
||||
g_variant_builder_add( &actions_builder, "s", _( "Open File" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
g_variant_builder_add( &actions_builder, "s", "folder" );
|
||||
g_variant_builder_add( &actions_builder, "s", _( "Open Folder" ) );
|
||||
}
|
||||
}
|
||||
|
||||
if( gtr_pref_flag_get( PREF_KEY_TORRENT_COMPLETE_NOTIFICATION_ENABLED ) )
|
||||
{
|
||||
const tr_torrent * tor = gtr_core_find_torrent( core, torrent_id );
|
||||
const char * fmt = gtr_pref_string_get( PREF_KEY_TORRENT_COMPLETE_NOTIFICATION_COMMAND );
|
||||
char * cmd = g_strdup_printf( fmt, _( "Torrent Complete" ), ( tor ? tr_torrentName( tor ) : "" ) );
|
||||
g_spawn_command_line_async( cmd, NULL );
|
||||
g_free( cmd );
|
||||
}
|
||||
g_dbus_proxy_call( proxy,
|
||||
"Notify",
|
||||
g_variant_new( "(susssasa{sv}i)",
|
||||
"Transmission", n->id, "transmission",
|
||||
_( "Torrent Complete" ),
|
||||
tr_torrentName( tor ),
|
||||
&actions_builder, NULL, -1 ),
|
||||
G_DBUS_CALL_FLAGS_NONE, -1, NULL,
|
||||
notify_callback, n );
|
||||
}
|
||||
|
||||
void
|
||||
gtr_notify_torrent_added( const char * name )
|
||||
{
|
||||
if( gtr_pref_flag_get( PREF_KEY_TORRENT_ADDED_NOTIFICATION_ENABLED ) )
|
||||
{
|
||||
const char * fmt = gtr_pref_string_get( PREF_KEY_TORRENT_ADDED_NOTIFICATION_COMMAND );
|
||||
char * cmd = g_strdup_printf( fmt, _( "Torrent Added" ), name );
|
||||
g_spawn_command_line_async( cmd, NULL );
|
||||
g_free( cmd );
|
||||
}
|
||||
TrNotification * n;
|
||||
|
||||
g_return_if_fail( G_IS_DBUS_PROXY( proxy ) );
|
||||
|
||||
if( !gtr_pref_flag_get( PREF_KEY_TORRENT_ADDED_NOTIFICATION_ENABLED ) )
|
||||
return;
|
||||
|
||||
n = g_new0( TrNotification, 1 );
|
||||
g_dbus_proxy_call( proxy,
|
||||
"Notify",
|
||||
g_variant_new( "(susssasa{sv}i)",
|
||||
"Transmission", 0, "transmission",
|
||||
_( "Torrent Added" ), name,
|
||||
NULL, NULL, -1 ),
|
||||
G_DBUS_CALL_FLAGS_NONE, -1, NULL,
|
||||
notify_callback, n );
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
|
||||
#include "tr-core.h"
|
||||
|
||||
void gtr_notify_init( void );
|
||||
|
||||
void gtr_notify_torrent_added ( const char * name );
|
||||
|
||||
void gtr_notify_torrent_completed ( TrCore * core, int torrent_id );
|
||||
|
|
|
@ -42,9 +42,7 @@ GtkWidget * gtr_prefs_dialog_new( GtkWindow * parent, GObject * core );
|
|||
#define PREF_KEY_STATUSBAR "show-statusbar"
|
||||
#define PREF_KEY_STATUSBAR_STATS "statusbar-stats"
|
||||
#define PREF_KEY_TOOLBAR "show-toolbar"
|
||||
#define PREF_KEY_TORRENT_ADDED_NOTIFICATION_COMMAND "torrent-added-notification-command"
|
||||
#define PREF_KEY_TORRENT_ADDED_NOTIFICATION_ENABLED "torrent-added-notification-enabled"
|
||||
#define PREF_KEY_TORRENT_COMPLETE_NOTIFICATION_COMMAND "torrent-complete-notification-command"
|
||||
#define PREF_KEY_TORRENT_COMPLETE_NOTIFICATION_ENABLED "torrent-complete-notification-enabled"
|
||||
#define PREF_KEY_TORRENT_COMPLETE_SOUND_COMMAND "torrent-complete-sound-command"
|
||||
#define PREF_KEY_TORRENT_COMPLETE_SOUND_ENABLED "torrent-complete-sound-enabled"
|
||||
|
|
Loading…
Reference in New Issue