2013-01-03 14:07:56 -08:00
# include "e.h"
typedef struct _Notification_Data
{
2022-06-17 16:44:17 -07:00
Eldbus_Connection * conn ;
Eldbus_Service_Interface * iface ;
2013-01-11 02:34:29 -08:00
E_Notification_Notify_Cb notify_cb ;
E_Notification_Close_Cb close_cb ;
void * data ;
2013-01-03 14:07:56 -08:00
const E_Notification_Server_Info * server_info ;
} Notification_Data ;
static Notification_Data * n_data = NULL ;
2013-04-25 01:12:43 -07:00
static void
_notification_free ( E_Notification_Notify * notify )
{
2022-06-17 16:44:17 -07:00
int i ;
2013-04-25 01:12:43 -07:00
EINA_SAFETY_ON_NULL_RETURN ( notify ) ;
2022-06-17 16:44:17 -07:00
if ( notify - > app_name ) eina_stringshare_del ( notify - > app_name ) ;
if ( notify - > body ) eina_stringshare_del ( notify - > body ) ;
if ( notify - > icon . icon ) eina_stringshare_del ( notify - > icon . icon ) ;
if ( notify - > icon . icon_path ) eina_stringshare_del ( notify - > icon . icon_path ) ;
if ( notify - > summary ) eina_stringshare_del ( notify - > summary ) ;
if ( notify - > icon . raw . data ) free ( notify - > icon . raw . data ) ;
if ( notify - > category ) eina_stringshare_del ( notify - > category ) ;
if ( notify - > desktop_entry ) eina_stringshare_del ( notify - > desktop_entry ) ;
if ( notify - > sound_file ) eina_stringshare_del ( notify - > sound_file ) ;
if ( notify - > sound_name ) eina_stringshare_del ( notify - > sound_name ) ;
if ( notify - > actions )
{
for ( i = 0 ; notify - > actions [ i ] . action ; i + + )
{
eina_stringshare_del ( notify - > actions [ i ] . action ) ;
eina_stringshare_del ( notify - > actions [ i ] . label ) ;
}
free ( notify - > actions ) ;
}
2013-04-25 01:12:43 -07:00
free ( notify ) ;
}
2013-01-03 14:07:56 -08:00
static void
2013-04-23 08:08:29 -07:00
hints_dict_iter ( void * data , const void * key , Eldbus_Message_Iter * var )
2013-01-03 14:07:56 -08:00
{
E_Notification_Notify * n = data ;
2022-06-17 16:44:17 -07:00
if ( ( ! strcmp ( key , " image-data " ) ) | | ( ! strcmp ( key , " image_data " ) ) | |
( ! strcmp ( key , " icon_data " ) ) )
2013-01-03 14:07:56 -08:00
{
2013-04-23 08:08:29 -07:00
Eldbus_Message_Iter * st , * data_iter ;
2013-01-03 14:07:56 -08:00
int w , h , r , bits , channels ;
Eina_Bool alpha ;
unsigned char * raw_data ;
2022-06-17 16:44:17 -07:00
2013-04-23 08:08:29 -07:00
if ( ! eldbus_message_iter_arguments_get ( var , " (iiibiiay) " , & st ) )
2013-01-03 14:07:56 -08:00
return ;
2013-04-23 08:08:29 -07:00
if ( ! eldbus_message_iter_arguments_get ( st , " iiibiiay " , & w , & h , & r ,
2013-01-03 14:07:56 -08:00
& alpha , & bits , & channels ,
& data_iter ) )
return ;
2013-04-23 08:08:29 -07:00
eldbus_message_iter_fixed_array_get ( data_iter , ' y ' , & raw_data ,
2013-01-03 14:07:56 -08:00
& n - > icon . raw . data_size ) ;
n - > icon . raw . width = w ;
n - > icon . raw . height = h ;
n - > icon . raw . has_alpha = alpha ;
n - > icon . raw . rowstride = r ;
n - > icon . raw . bits_per_sample = bits ;
n - > icon . raw . channels = channels ;
n - > icon . raw . data = malloc ( sizeof ( char ) * n - > icon . raw . data_size ) ;
EINA_SAFETY_ON_NULL_RETURN ( n - > icon . raw . data ) ;
2013-01-11 02:34:29 -08:00
memcpy ( n - > icon . raw . data , raw_data , sizeof ( char ) * n - > icon . raw . data_size ) ;
2022-06-17 16:44:17 -07:00
printf ( " NOT: image-data=%ix%i,a=%i \n " , w , h , alpha ) ;
}
else if ( ! strcmp ( key , " image-path " ) | | ! strcmp ( key , " image_path " ) )
{
eldbus_message_iter_arguments_get ( var , " s " , & n - > icon . icon_path ) ;
n - > icon . icon_path = eina_stringshare_add ( n - > icon . icon_path ) ;
printf ( " NOT: image-path=[%s] \n " , n - > icon . icon_path ) ;
// path to image file
2013-01-03 14:07:56 -08:00
}
else if ( ! strcmp ( key , " urgency " ) )
{
unsigned char urgency ;
2022-06-17 16:44:17 -07:00
2013-04-23 08:08:29 -07:00
eldbus_message_iter_arguments_get ( var , " y " , & urgency ) ;
2022-06-17 16:44:17 -07:00
if ( urgency < 3 ) n - > urgency = urgency ;
printf ( " NOT: urgency=%i \n " , n - > urgency ) ;
// 0=low, 1=normal, 2=critical
2013-01-03 14:07:56 -08:00
}
2022-06-17 16:44:17 -07:00
else if ( ! strcmp ( key , " category " ) )
{ // XXX: store category
const char * val = NULL ;
eldbus_message_iter_arguments_get ( var , " s " , & val ) ;
printf ( " NOT: category=[%s] \n " , val ) ;
// "device" A generic device-related notification that doesn't fit into any other category.
// "device.added" A device, such as a USB device, was added to the system.
// "device.error" A device had some kind of error.
// "device.removed" A device, such as a USB device, was removed from the system.
// "email" A generic e-mail-related notification that doesn't fit into any other category.
// "email.arrived" A new e-mail notification.
// "email.bounced" A notification stating that an e-mail has bounced.
// "im" A generic instant message-related notification that doesn't fit into any other category.
// "im.error" An instant message error notification.
// "im.received" A received instant message notification.
// "network" A generic network notification that doesn't fit into any other category.
// "network.connected" A network connection notification, such as successful sign-on to a network service. This should not be confused with device.added for new network devices.
// "network.disconnected" A network disconnected notification. This should not be confused with device.removed for disconnected network devices.
// "network.error" A network-related or connection-related error.
// "presence" A generic presence change notification that doesn't fit into any other category, such as going away or idle.
// "presence.offline" An offline presence change notification.
// "presence.online" An online presence change notification.
// "transfer" A generic file transfer or download notification that doesn't fit into any other category.
// "transfer.complete" A file transfer or download complete notification.
// "transfer.error" A file transfer or download error.
if ( val ) n - > category = eina_stringshare_add ( val ) ;
}
else if ( ! strcmp ( key , " desktop-entry " ) )
2013-01-03 14:07:56 -08:00
{
2022-06-17 16:44:17 -07:00
const char * val = NULL ;
eldbus_message_iter_arguments_get ( var , " s " , & val ) ;
printf ( " NOT: desktop-entry=[%s] \n " , val ) ;
// if rage.desktop -> "rage"
// if terminology.desktop -> "terminology"
if ( val ) n - > desktop_entry = eina_stringshare_add ( val ) ;
2013-01-03 14:07:56 -08:00
}
2022-06-17 16:44:17 -07:00
else if ( ! strcmp ( key , " icon-actions " ) )
{
Eina_Bool val = 0 ;
eldbus_message_iter_arguments_get ( var , " b " , & val ) ;
printf ( " NOT: icon-actions=%i \n " , val ) ;
// 1 == interpret action identifier == named icon in icon naming standards
n - > icon_actions = val ;
}
else if ( ! strcmp ( key , " resident " ) )
{
Eina_Bool val = 0 ;
eldbus_message_iter_arguments_get ( var , " b " , & val ) ;
printf ( " NOT: resident=%i \n " , val ) ;
// 1== remove notification when action invoked - no timeout
n - > resident = val ;
}
2022-09-09 01:40:38 -07:00
else if ( ! strcmp ( key , " suppress-sound " ) )
2022-06-17 16:44:17 -07:00
{
Eina_Bool val = 0 ;
2013-01-03 14:07:56 -08:00
2022-06-17 16:44:17 -07:00
eldbus_message_iter_arguments_get ( var , " b " , & val ) ;
2022-09-09 01:40:38 -07:00
printf ( " NOT: suppress-sound=%i \n " , val ) ;
2022-06-17 16:44:17 -07:00
// 1== remove notification when action invoked - no timeout
n - > suppress_sound = val ;
}
else if ( ! strcmp ( key , " sound-file " ) )
{
const char * val = NULL ;
eldbus_message_iter_arguments_get ( var , " s " , & val ) ;
printf ( " NOT: sound-file=[%s] \n " , val ) ;
// path to sound file to play
if ( val ) n - > sound_file = eina_stringshare_add ( val ) ;
}
else if ( ! strcmp ( key , " sound-name " ) )
{
const char * val = NULL ;
eldbus_message_iter_arguments_get ( var , " s " , & val ) ;
printf ( " NOT: sound-file=[%s] \n " , val ) ;
// sound naming spec to play
// http://0pointer.de/public/sound-naming-spec.html
if ( val ) n - > sound_name = eina_stringshare_add ( val ) ;
}
else if ( ! strcmp ( key , " transient " ) )
{
Eina_Bool val = 0 ;
eldbus_message_iter_arguments_get ( var , " b " , & val ) ;
printf ( " NOT: transient=%i \n " , val ) ;
n - > transient = val ;
}
else if ( ! strcmp ( key , " x " ) )
{
int val = 0 ;
eldbus_message_iter_arguments_get ( var , " i " , & val ) ;
printf ( " NOT: x=%i \n " , val ) ;
n - > x = val ;
n - > have_xy = EINA_TRUE ;
}
else if ( ! strcmp ( key , " y " ) )
{
int val = 0 ;
eldbus_message_iter_arguments_get ( var , " i " , & val ) ;
printf ( " NOT: y=%i \n " , val ) ;
n - > y = val ;
n - > have_xy = EINA_TRUE ;
}
}
2016-03-30 13:08:05 -07:00
2022-06-17 16:44:17 -07:00
static int
_tag_len ( const char * txt )
2016-03-30 13:08:05 -07:00
{
2022-06-17 16:44:17 -07:00
const char * s ;
Eina_Bool backslash = EINA_FALSE ;
Eina_Bool inquote = EINA_FALSE , indblquote = EINA_FALSE ;
2016-03-30 13:08:05 -07:00
2022-06-17 16:44:17 -07:00
if ( txt [ 0 ] ! = ' < ' ) return 0 ;
for ( s = txt ; * s ; s + + )
{
if ( ! backslash )
{
if ( * s = = ' \\ ' ) backslash = EINA_TRUE ;
else
{
if ( inquote )
{
if ( * s = = ' \' ' ) inquote = EINA_FALSE ;
}
else if ( indblquote )
{
if ( * s = = ' " ' ) indblquote = EINA_FALSE ;
}
else
{
if ( * s = = ' > ' )
{
s + + ;
break ;
}
else if ( * s = = ' \' ' ) inquote = EINA_TRUE ;
else if ( * s = = ' \" ' ) indblquote = EINA_TRUE ;
}
}
}
else backslash = EINA_FALSE ;
}
return s - txt ;
}
static char *
_path_get ( const char * txt )
2016-03-30 13:08:05 -07:00
{
2022-06-17 16:44:17 -07:00
Eina_Strbuf * buf ;
char * ret ;
const char * s ;
Eina_Bool backslash = EINA_FALSE ;
Eina_Bool inquote = EINA_FALSE , indblquote = EINA_FALSE ;
2016-03-30 13:08:05 -07:00
2022-06-17 16:44:17 -07:00
if ( txt [ 0 ] = = ' > ' ) return NULL ;
buf = eina_strbuf_new ( ) ;
if ( ! buf ) return NULL ;
for ( s = txt ; * s ; s + + )
{
if ( ! backslash )
{
if ( * s = = ' \\ ' ) backslash = EINA_TRUE ;
else
{
if ( inquote )
{
if ( * s = = ' \' ' ) inquote = EINA_FALSE ;
else eina_strbuf_append_char ( buf , * s ) ;
}
else if ( indblquote )
{
if ( * s = = ' " ' ) indblquote = EINA_FALSE ;
else eina_strbuf_append_char ( buf , * s ) ;
}
else
{
if ( * s = = ' > ' ) break ;
else if ( * s = = ' ' ) break ;
else if ( * s = = ' \' ' ) inquote = EINA_TRUE ;
else if ( * s = = ' \" ' ) indblquote = EINA_TRUE ;
else eina_strbuf_append_char ( buf , * s ) ;
}
}
}
else
{
eina_strbuf_append_char ( buf , * s ) ;
backslash = EINA_FALSE ;
}
}
ret = eina_strbuf_string_steal ( buf ) ;
eina_strbuf_free ( buf ) ;
return ret ;
2016-03-30 13:08:05 -07:00
}
2022-06-17 16:44:17 -07:00
static char *
2016-03-30 13:08:05 -07:00
_nedje_text_escape ( const char * text )
{
Eina_Strbuf * txt ;
char * ret ;
const char * text_end ;
2022-06-17 16:44:17 -07:00
int taglen ;
2016-03-30 13:08:05 -07:00
if ( ! text ) return NULL ;
txt = eina_strbuf_new ( ) ;
2022-06-17 16:44:17 -07:00
if ( ! txt ) return NULL ;
text_end = text + strlen ( text ) ;
2016-03-30 13:08:05 -07:00
while ( text < text_end )
{
2022-06-17 16:44:17 -07:00
taglen = _tag_len ( text ) ;
if ( taglen = = 0 )
2016-03-30 13:08:05 -07:00
{
2022-06-17 16:44:17 -07:00
eina_strbuf_append_char ( txt , text [ 0 ] ) ;
text + + ;
}
else
{
if ( ! strncmp ( text , " <b> " , 3 ) ) eina_strbuf_append ( txt , " <b> " ) ;
else if ( ! strncmp ( text , " </b> " , 4 ) ) eina_strbuf_append ( txt , " </b> " ) ;
else if ( ! strncmp ( text , " <i> " , 3 ) ) eina_strbuf_append ( txt , " <i> " ) ;
else if ( ! strncmp ( text , " </i> " , 4 ) ) eina_strbuf_append ( txt , " </i> " ) ;
else if ( ! strncmp ( text , " <u> " , 3 ) ) eina_strbuf_append ( txt , " <u> " ) ;
else if ( ! strncmp ( text , " </u> " , 4 ) ) eina_strbuf_append ( txt , " </u> " ) ;
else if ( ! strncmp ( text , " <a " , 3 ) )
2016-03-30 13:08:05 -07:00
{
2022-06-17 16:44:17 -07:00
eina_strbuf_append ( txt , " <link> " ) ;
eina_strbuf_append_n ( txt , text , taglen ) ;
2016-03-30 13:08:05 -07:00
}
2022-06-17 16:44:17 -07:00
else if ( ! strncmp ( text , " </a> " , 3 ) )
2016-03-30 13:08:05 -07:00
{
2022-06-17 16:44:17 -07:00
eina_strbuf_append ( txt , " </a></link> " ) ;
2016-03-30 13:08:05 -07:00
}
2022-06-17 16:44:17 -07:00
else if ( ! strncmp ( text , " <img src= " , 9 ) )
2016-03-30 13:08:05 -07:00
{
2022-06-17 16:44:17 -07:00
Evas_Object * o ;
int w = 0 , h = 0 ;
char * path ;
path = _path_get ( text + 9 ) ;
if ( ( path ) & & ( strlen ( path ) > 0 ) )
2016-03-30 13:08:05 -07:00
{
2022-06-17 16:44:17 -07:00
o = evas_object_image_add ( e_comp - > evas ) ;
evas_object_image_file_set ( o , path , NULL ) ;
evas_object_image_size_get ( o , & w , & h ) ;
printf ( " NOT: imgpath=%s %ix%i \n " , path , w , h ) ;
if ( ( w > 0 ) & & ( h > 0 ) )
{
double neww = w , newh = h ;
if ( neww > 200.0 )
{
double oldw = neww ;
neww = 200.0 ;
newh = ( newh * neww ) / oldw ;
}
if ( newh > 100.0 )
{
double oldh = newh ;
newh = 100.0 ;
neww = ( neww * newh ) / oldh ;
}
neww * = e_scale ;
newh * = e_scale ;
w = neww + 0.5 ;
h = newh + 0.5 ;
eina_strbuf_append_printf
( txt , " <item absize=%ix%i href= " , w , h ) ;
eina_strbuf_append_n ( txt , text + 9 , taglen - 9 ) ;
eina_strbuf_append ( txt , " </item> " ) ;
}
evas_object_del ( o ) ;
2016-03-30 13:08:05 -07:00
}
2022-06-17 16:44:17 -07:00
free ( path ) ;
2016-03-30 13:08:05 -07:00
}
2022-06-17 16:44:17 -07:00
text + = taglen ;
2016-03-30 13:08:05 -07:00
}
}
ret = eina_strbuf_string_steal ( txt ) ;
2022-06-17 16:44:17 -07:00
printf ( " NOT: body -> [%s] \n " , ret ) ;
2016-03-30 13:08:05 -07:00
eina_strbuf_free ( txt ) ;
return ret ;
}
2013-04-23 08:08:29 -07:00
static Eldbus_Message *
notify_cb ( const Eldbus_Service_Interface * iface EINA_UNUSED , const Eldbus_Message * msg )
2013-01-03 14:07:56 -08:00
{
E_Notification_Notify * n ;
2013-04-23 08:08:29 -07:00
Eldbus_Message_Iter * actions_iter , * hints_iter ;
Eldbus_Message * reply ;
2022-06-17 16:44:17 -07:00
char * txt , * txt2 ;
int num ;
2013-01-03 14:07:56 -08:00
2022-06-17 16:44:17 -07:00
if ( ! n_data - > notify_cb ) return NULL ;
2013-01-03 14:07:56 -08:00
2013-04-25 01:12:43 -07:00
n = E_OBJECT_ALLOC ( E_Notification_Notify , E_NOTIFICATION_TYPE , _notification_free ) ;
2013-04-26 00:53:16 -07:00
n - > urgency = E_NOTIFICATION_NOTIFY_URGENCY_NORMAL ;
2022-06-17 16:44:17 -07:00
if ( ! eldbus_message_arguments_get ( msg , " susssasa{sv}i " ,
& n - > app_name , & n - > replaces_id ,
& n - > icon . icon , & n - > summary , & n - > body ,
& actions_iter , & hints_iter , & n - > timeout ) )
2013-01-03 14:07:56 -08:00
{
ERR ( " Reading message. " ) ;
2013-04-25 01:12:43 -07:00
e_object_del ( E_OBJECT ( n ) ) ;
2013-01-03 14:07:56 -08:00
return NULL ;
}
2014-01-20 13:08:14 -08:00
if ( e_screensaver_on_get ( ) & & e_config - > screensaver_wake_on_notify )
2022-06-17 16:44:17 -07:00
{ // XXX: this is an attempt to wake the screen? should be an option
2014-01-20 13:08:14 -08:00
int x , y ;
2022-06-17 16:44:17 -07:00
2015-01-23 04:49:09 -08:00
ecore_evas_pointer_xy_get ( e_comp - > ee , & x , & y ) ;
ecore_evas_pointer_warp ( e_comp - > ee , x , y ) ;
2014-01-20 13:08:14 -08:00
}
2022-06-17 16:44:17 -07:00
// walk hints
2013-04-23 08:08:29 -07:00
eldbus_message_iter_dict_iterate ( hints_iter , " sv " , hints_dict_iter , n ) ;
2013-01-03 14:07:56 -08:00
n - > app_name = eina_stringshare_add ( n - > app_name ) ;
n - > icon . icon = eina_stringshare_add ( n - > icon . icon ) ;
2014-07-30 16:18:24 -07:00
n - > summary = eina_stringshare_add ( n - > summary ) ;
2016-03-30 13:08:05 -07:00
txt = _nedje_text_escape ( n - > body ) ;
n - > body = eina_stringshare_add ( txt ) ;
free ( txt ) ;
2013-01-03 14:07:56 -08:00
2022-06-17 16:44:17 -07:00
num = 0 ;
while ( eldbus_message_iter_get_and_next ( actions_iter , ' s ' , & txt ) )
{
if ( eldbus_message_iter_get_and_next ( actions_iter , ' s ' , & txt2 ) )
{ // XXX: add actions to notification
E_Notification_Notify_Action * actions ;
printf ( " NOT: act=[%s] [%s] \n " , txt , txt2 ) ;
num + + ;
actions = realloc ( n - > actions , ( num + 1 ) * sizeof ( E_Notification_Notify ) ) ;
if ( actions )
{
n - > actions = actions ;
n - > actions [ num - 1 ] . action = eina_stringshare_add ( txt ) ;
n - > actions [ num - 1 ] . label = eina_stringshare_add ( txt2 ) ;
n - > actions [ num ] . action = NULL ;
n - > actions [ num ] . label = NULL ;
}
}
}
2013-04-25 01:12:43 -07:00
e_object_ref ( E_OBJECT ( n ) ) ;
2013-01-03 14:08:00 -08:00
n - > id = n_data - > notify_cb ( n_data - > data , n ) ;
2013-04-23 08:08:29 -07:00
reply = eldbus_message_method_return_new ( msg ) ;
eldbus_message_arguments_append ( reply , " u " , n - > id ) ;
2013-04-25 01:12:43 -07:00
e_object_unref ( E_OBJECT ( n ) ) ;
2022-06-17 16:44:17 -07:00
2013-01-03 14:07:56 -08:00
return reply ;
}
2013-04-23 08:08:29 -07:00
static Eldbus_Message *
close_notification_cb ( const Eldbus_Service_Interface * iface EINA_UNUSED , const Eldbus_Message * msg )
2013-01-03 14:07:56 -08:00
{
2022-06-17 16:44:17 -07:00
unsigned int id ;
if ( ! eldbus_message_arguments_get ( msg , " u " , & id ) ) return NULL ;
if ( n_data - > close_cb ) n_data - > close_cb ( n_data - > data , id ) ;
2013-04-23 08:08:29 -07:00
return eldbus_message_method_return_new ( msg ) ;
2013-01-03 14:07:56 -08:00
}
2013-04-23 08:08:29 -07:00
static Eldbus_Message *
capabilities_cb ( const Eldbus_Service_Interface * iface EINA_UNUSED , const Eldbus_Message * msg )
2013-01-03 14:07:56 -08:00
{
2013-04-23 08:08:29 -07:00
Eldbus_Message * reply = eldbus_message_method_return_new ( msg ) ;
2013-01-03 14:07:56 -08:00
int i ;
2013-04-23 08:08:29 -07:00
Eldbus_Message_Iter * main_iter , * array ;
2013-01-03 14:07:56 -08:00
2013-04-23 08:08:29 -07:00
main_iter = eldbus_message_iter_get ( reply ) ;
eldbus_message_iter_arguments_append ( main_iter , " as " , & array ) ;
2013-01-03 14:07:56 -08:00
for ( i = 0 ; n_data - > server_info - > capabilities [ i ] ; i + + )
2022-06-17 16:44:17 -07:00
{
eldbus_message_iter_arguments_append
( array , " s " , n_data - > server_info - > capabilities [ i ] ) ;
}
2013-04-23 08:08:29 -07:00
eldbus_message_iter_container_close ( main_iter , array ) ;
2013-01-03 14:07:56 -08:00
return reply ;
}
2013-04-23 08:08:29 -07:00
static Eldbus_Message *
server_info_cb ( const Eldbus_Service_Interface * iface EINA_UNUSED , const Eldbus_Message * msg )
2013-01-03 14:07:56 -08:00
{
2013-04-23 08:08:29 -07:00
Eldbus_Message * reply = eldbus_message_method_return_new ( msg ) ;
2022-06-17 16:44:17 -07:00
eldbus_message_arguments_append ( reply , " ssss " ,
n_data - > server_info - > name ,
n_data - > server_info - > vendor ,
n_data - > server_info - > version ,
n_data - > server_info - > spec_version ) ;
2013-01-03 14:07:56 -08:00
return reply ;
}
2013-04-23 08:08:29 -07:00
static const Eldbus_Method methods [ ] = {
2013-01-03 14:07:56 -08:00
{ " Notify " ,
2022-06-17 16:44:17 -07:00
ELDBUS_ARGS ( { " s " , " app_name " } , { " u " , " replaces_id " } , { " s " , " app_icon " } , { " s " , " summary " } , { " s " , " body " } , { " as " , " actions " } , { " a{sv} " , " hints " } , { " i " , " expire_timeout " } ) ,
ELDBUS_ARGS ( { " u " , " id " } ) ,
notify_cb , 0 } ,
{ " CloseNotification " ,
ELDBUS_ARGS ( { " u " , " id " } ) ,
NULL ,
close_notification_cb , 0 } ,
{ " GetCapabilities " ,
NULL ,
ELDBUS_ARGS ( { " as " , " capabilities " } ) ,
capabilities_cb , 0 } ,
{ " GetServerInformation " ,
NULL ,
ELDBUS_ARGS ( { " s " , " name " } , { " s " , " vendor " } , { " s " , " version " } , { " s " , " spec_version " } ) ,
server_info_cb , 0 } ,
2014-09-18 10:29:52 -07:00
{ NULL , NULL , NULL , NULL , 0 }
2013-01-03 14:08:00 -08:00
} ;
enum
{
SIGNAL_NOTIFICATION_CLOSED = 0 ,
SIGNAL_ACTION_INVOKED ,
2013-01-03 14:07:56 -08:00
} ;
2013-04-23 08:08:29 -07:00
static const Eldbus_Signal signals [ ] = {
2013-01-03 14:08:00 -08:00
[ SIGNAL_NOTIFICATION_CLOSED ] =
2014-09-18 10:29:52 -07:00
{ " NotificationClosed " , ELDBUS_ARGS ( { " u " , " id " } , { " u " , " reason " } ) , 0 } ,
2013-01-03 14:08:00 -08:00
[ SIGNAL_ACTION_INVOKED ] =
2014-09-18 10:29:52 -07:00
{ " ActionInvoked " , ELDBUS_ARGS ( { " u " , " id " } , { " s " , " action_key " } ) , 0 } ,
2022-06-17 16:44:17 -07:00
2014-09-18 10:29:52 -07:00
{ NULL , NULL , 0 }
2013-01-03 14:07:56 -08:00
} ;
# define PATH " / org / freedesktop / Notifications"
# define BUS "org.freedesktop.Notifications"
# define INTERFACE "org.freedesktop.Notifications"
2013-04-23 08:08:29 -07:00
static const Eldbus_Service_Interface_Desc desc = {
2013-01-03 14:07:56 -08:00
INTERFACE , methods , signals , NULL , NULL , NULL
} ;
2015-05-07 12:13:10 -07:00
E_API Eina_Bool
2013-01-03 14:08:00 -08:00
e_notification_server_register ( const E_Notification_Server_Info * server_info , E_Notification_Notify_Cb n_cb , E_Notification_Close_Cb close_cb , const void * data )
2013-01-03 14:07:56 -08:00
{
EINA_SAFETY_ON_NULL_RETURN_VAL ( server_info , EINA_FALSE ) ;
2022-06-17 16:44:17 -07:00
if ( n_data ) return EINA_FALSE ;
2013-01-03 14:07:56 -08:00
n_data = calloc ( 1 , sizeof ( Notification_Data ) ) ;
EINA_SAFETY_ON_NULL_RETURN_VAL ( n_data , EINA_FALSE ) ;
2013-04-23 08:08:29 -07:00
n_data - > conn = eldbus_connection_get ( ELDBUS_CONNECTION_TYPE_SESSION ) ;
n_data - > iface = eldbus_service_interface_register ( n_data - > conn , PATH , & desc ) ;
2013-01-03 14:08:00 -08:00
n_data - > notify_cb = n_cb ;
2013-01-03 14:07:56 -08:00
n_data - > close_cb = close_cb ;
2013-01-11 02:34:29 -08:00
n_data - > data = ( void * ) data ;
2013-01-03 14:07:56 -08:00
n_data - > server_info = server_info ;
2013-04-23 08:08:29 -07:00
eldbus_name_request ( n_data - > conn , BUS ,
2022-06-17 16:44:17 -07:00
ELDBUS_NAME_REQUEST_FLAG_REPLACE_EXISTING , NULL , NULL ) ;
2013-01-03 14:07:56 -08:00
return EINA_TRUE ;
}
2015-05-07 12:13:10 -07:00
E_API void
2013-01-03 14:08:00 -08:00
e_notification_server_unregister ( void )
2013-01-03 14:07:56 -08:00
{
EINA_SAFETY_ON_NULL_RETURN ( n_data ) ;
2013-04-23 08:08:29 -07:00
eldbus_service_interface_unregister ( n_data - > iface ) ;
eldbus_connection_unref ( n_data - > conn ) ;
2013-01-03 14:07:56 -08:00
free ( n_data ) ;
n_data = NULL ;
}
2015-05-07 12:13:10 -07:00
E_API void
2013-01-03 14:08:00 -08:00
e_notification_notify_close ( E_Notification_Notify * notify , E_Notification_Notify_Closed_Reason reason )
2013-01-03 14:07:56 -08:00
{
EINA_SAFETY_ON_NULL_RETURN ( n_data ) ;
2013-01-03 14:08:00 -08:00
EINA_SAFETY_ON_NULL_RETURN ( notify ) ;
EINA_SAFETY_ON_FALSE_RETURN ( reason < = E_NOTIFICATION_NOTIFY_CLOSED_REASON_UNDEFINED ) ;
2013-04-23 08:08:29 -07:00
eldbus_service_signal_emit ( n_data - > iface , SIGNAL_NOTIFICATION_CLOSED ,
2022-06-17 16:44:17 -07:00
notify - > id , reason ) ;
}
E_API void
e_notification_notify_action ( E_Notification_Notify * notify , const char * action )
{
EINA_SAFETY_ON_NULL_RETURN ( n_data ) ;
EINA_SAFETY_ON_NULL_RETURN ( notify ) ;
if ( ! action ) action = " " ;
eldbus_service_signal_emit ( n_data - > iface , SIGNAL_ACTION_INVOKED ,
notify - > id , action ) ;
2013-01-03 14:07:56 -08:00
}
2015-05-07 12:13:10 -07:00
E_API Evas_Object *
2013-01-03 14:08:00 -08:00
e_notification_notify_raw_image_get ( E_Notification_Notify * notify , Evas * evas )
2013-01-03 14:07:56 -08:00
{
Evas_Object * o ;
unsigned char * imgdata ;
EINA_SAFETY_ON_NULL_RETURN_VAL ( notify , NULL ) ;
EINA_SAFETY_ON_NULL_RETURN_VAL ( evas , NULL ) ;
EINA_SAFETY_ON_NULL_RETURN_VAL ( notify - > icon . raw . data , NULL ) ;
o = evas_object_image_filled_add ( evas ) ;
evas_object_resize ( o , notify - > icon . raw . width , notify - > icon . raw . height ) ;
evas_object_image_colorspace_set ( o , EVAS_COLORSPACE_ARGB8888 ) ;
evas_object_image_alpha_set ( o , notify - > icon . raw . has_alpha ) ;
evas_object_image_size_set ( o , notify - > icon . raw . width , notify - > icon . raw . height ) ;
imgdata = evas_object_image_data_get ( o , EINA_TRUE ) ;
EINA_SAFETY_ON_NULL_GOTO ( imgdata , error ) ;
if ( notify - > icon . raw . bits_per_sample = = 8 )
{
/* Although not specified.
* The data are very likely to come from a GdkPixbuf
* which align each row on a 4 - bytes boundary when using RGB .
* And is RGBA otherwise . */
int x , y , * d ;
unsigned char * s ;
int rowstride = evas_object_image_stride_get ( o ) ;
for ( y = 0 ; y < notify - > icon . raw . height ; y + + )
{
s = notify - > icon . raw . data + ( y * notify - > icon . raw . rowstride ) ;
2017-02-11 22:30:10 -08:00
d = ( int * ) ( void * ) ( imgdata + ( y * rowstride ) ) ;
2013-01-03 14:07:56 -08:00
for ( x = 0 ; x < notify - > icon . raw . width ;
x + + , s + = notify - > icon . raw . channels , d + + )
{
if ( notify - > icon . raw . has_alpha )
* d = ( s [ 3 ] < < 24 ) | ( s [ 0 ] < < 16 ) | ( s [ 1 ] < < 8 ) | ( s [ 2 ] ) ;
else
* d = ( 0xff < < 24 ) | ( s [ 0 ] < < 16 ) | ( s [ 1 ] < < 8 ) | ( s [ 2 ] ) ;
}
}
}
evas_object_image_data_update_add ( o , 0 , 0 , notify - > icon . raw . width ,
notify - > icon . raw . height ) ;
evas_object_image_data_set ( o , imgdata ) ;
return o ;
error :
evas_object_del ( o ) ;
return NULL ;
}
2013-01-03 14:08:10 -08:00
/* client API */
static void
2013-04-23 08:08:29 -07:00
client_notify_cb ( void * data , const Eldbus_Message * msg , Eldbus_Pending * pending )
2013-01-03 14:08:10 -08:00
{
unsigned id = 0 ;
2013-04-23 08:08:29 -07:00
E_Notification_Client_Send_Cb cb = eldbus_pending_data_del ( pending , " cb " ) ;
Eldbus_Connection * conn = eldbus_pending_data_del ( pending , " conn " ) ;
if ( eldbus_message_error_get ( msg , NULL , NULL ) )
2013-01-03 14:08:10 -08:00
goto end ;
2013-04-23 08:08:29 -07:00
if ( ! eldbus_message_arguments_get ( msg , " u " , & id ) )
2013-01-03 14:08:10 -08:00
goto end ;
end :
2018-01-22 13:06:42 -08:00
if ( cb )
cb ( data , id ) ;
2013-04-23 08:08:29 -07:00
eldbus_connection_unref ( conn ) ;
eldbus_shutdown ( ) ;
2013-01-03 14:08:10 -08:00
}
static Eina_Bool
2013-01-03 14:08:19 -08:00
notification_client_dbus_send ( E_Notification_Notify * notify , E_Notification_Client_Send_Cb cb , const void * data )
2013-01-03 14:08:10 -08:00
{
2013-04-23 08:08:29 -07:00
Eldbus_Connection * conn ;
Eldbus_Message * msg ;
Eldbus_Message_Iter * main_iter , * actions , * hints ;
Eldbus_Message_Iter * entry , * var ;
Eldbus_Pending * p ;
2013-01-03 14:08:10 -08:00
EINA_SAFETY_ON_NULL_RETURN_VAL ( notify , EINA_FALSE ) ;
2013-04-23 08:08:29 -07:00
eldbus_init ( ) ;
conn = eldbus_connection_get ( ELDBUS_CONNECTION_TYPE_SESSION ) ;
2013-01-03 14:08:10 -08:00
EINA_SAFETY_ON_NULL_RETURN_VAL ( conn , EINA_FALSE ) ;
2013-04-23 08:08:29 -07:00
msg = eldbus_message_method_call_new ( BUS , PATH , INTERFACE , " Notify " ) ;
2013-01-03 14:08:10 -08:00
EINA_SAFETY_ON_NULL_RETURN_VAL ( msg , EINA_FALSE ) ;
//build message
2013-04-23 08:08:29 -07:00
main_iter = eldbus_message_iter_get ( msg ) ;
if ( ! eldbus_message_iter_arguments_append ( main_iter , " susssas " ,
2013-01-11 02:34:29 -08:00
notify - > app_name ? : " " ,
2013-01-03 14:08:10 -08:00
notify - > replaces_id ,
2013-01-11 02:34:29 -08:00
notify - > icon . icon ? : " " ,
2014-07-30 16:18:24 -07:00
notify - > summary ? : " " ,
2013-01-11 02:34:29 -08:00
notify - > body ? : " " ,
2013-01-03 14:08:10 -08:00
& actions ) )
goto error ;
2013-04-23 08:08:29 -07:00
eldbus_message_iter_container_close ( main_iter , actions ) ;
if ( ! eldbus_message_iter_arguments_append ( main_iter , " a{sv} " , & hints ) )
2013-01-03 14:08:10 -08:00
goto error ;
if ( notify - > icon . raw . data )
{
2013-04-23 08:08:29 -07:00
Eldbus_Message_Iter * st , * data_iter ;
2013-01-03 14:08:10 -08:00
int i ;
2022-06-17 16:44:17 -07:00
2013-04-23 08:08:29 -07:00
eldbus_message_iter_arguments_append ( hints , " {sv} " , & entry ) ;
eldbus_message_iter_arguments_append ( entry , " s " , " image-data " ) ;
var = eldbus_message_iter_container_new ( entry , ' v ' , " (iiibiiay) " ) ;
eldbus_message_iter_arguments_append ( var , " (iiibiiay) " , & st ) ;
eldbus_message_iter_arguments_append ( st , " iiibiiay " ,
2013-01-03 14:08:10 -08:00
notify - > icon . raw . width ,
notify - > icon . raw . height ,
notify - > icon . raw . rowstride ,
notify - > icon . raw . has_alpha ,
notify - > icon . raw . bits_per_sample ,
notify - > icon . raw . channels ,
& data_iter ) ;
for ( i = 0 ; i < notify - > icon . raw . data_size ; i + + )
2013-04-23 08:08:29 -07:00
eldbus_message_iter_basic_append ( data_iter , ' y ' , notify - > icon . raw . data [ i ] ) ;
eldbus_message_iter_container_close ( st , data_iter ) ;
eldbus_message_iter_container_close ( var , st ) ;
eldbus_message_iter_container_close ( entry , var ) ;
eldbus_message_iter_container_close ( hints , entry ) ;
2013-01-03 14:08:10 -08:00
}
if ( notify - > icon . icon_path )
{
2013-04-23 08:08:29 -07:00
eldbus_message_iter_arguments_append ( hints , " {sv} " , & entry ) ;
eldbus_message_iter_arguments_append ( entry , " s " , " image-path " ) ;
var = eldbus_message_iter_container_new ( entry , ' v ' , " s " ) ;
eldbus_message_iter_arguments_append ( var , " s " , notify - > icon . icon_path ) ;
eldbus_message_iter_container_close ( entry , var ) ;
eldbus_message_iter_container_close ( hints , entry ) ;
2013-01-03 14:08:10 -08:00
}
2013-04-23 08:08:29 -07:00
eldbus_message_iter_arguments_append ( hints , " {sv} " , & entry ) ;
eldbus_message_iter_arguments_append ( entry , " s " , " urgency " ) ;
var = eldbus_message_iter_container_new ( entry , ' v ' , " y " ) ;
eldbus_message_iter_arguments_append ( var , " y " , notify - > urgency ) ;
eldbus_message_iter_container_close ( entry , var ) ;
eldbus_message_iter_container_close ( hints , entry ) ;
2013-01-03 14:08:10 -08:00
2013-04-23 08:08:29 -07:00
eldbus_message_iter_container_close ( main_iter , hints ) ;
2013-01-03 14:08:10 -08:00
2013-04-23 08:08:29 -07:00
eldbus_message_iter_arguments_append ( main_iter , " i " , notify - > timeout ) ;
2013-01-03 14:08:10 -08:00
2013-04-23 08:08:29 -07:00
p = eldbus_connection_send ( conn , msg , client_notify_cb , data , 5000 ) ;
2013-01-03 14:08:10 -08:00
EINA_SAFETY_ON_NULL_GOTO ( p , error ) ;
2022-06-17 16:44:17 -07:00
if ( cb ) eldbus_pending_data_set ( p , " cb " , cb ) ;
2013-04-23 08:08:29 -07:00
eldbus_pending_data_set ( p , " conn " , conn ) ;
2013-01-15 06:34:50 -08:00
2013-01-03 14:08:10 -08:00
return EINA_TRUE ;
2013-01-15 06:34:50 -08:00
2013-01-03 14:08:10 -08:00
error :
2013-04-23 08:08:29 -07:00
eldbus_message_unref ( msg ) ;
2013-01-03 14:08:10 -08:00
return EINA_FALSE ;
}
static void
normalize_notify ( E_Notification_Notify * notify )
{
2022-06-17 16:44:17 -07:00
if ( ! notify - > timeout ) notify - > timeout = - 1 ;
2013-01-03 14:08:10 -08:00
}
2015-05-07 12:13:10 -07:00
E_API Eina_Bool
2013-01-03 14:08:10 -08:00
e_notification_client_send ( E_Notification_Notify * notify , E_Notification_Client_Send_Cb cb , const void * data )
{
unsigned id ;
E_Notification_Notify * copy ;
EINA_SAFETY_ON_NULL_RETURN_VAL ( notify , EINA_FALSE ) ;
normalize_notify ( notify ) ;
2013-01-03 14:08:19 -08:00
2013-01-03 14:08:10 -08:00
if ( ! n_data )
2018-01-22 13:52:00 -08:00
{
2022-06-17 16:44:17 -07:00
fprintf ( stderr , " UNHANDLED NOTIFICATION: \n Summary: %s \n Body: %s \n " ,
notify - > summary , notify - > body ) ;
2018-01-22 13:52:00 -08:00
return notification_client_dbus_send ( notify , cb , data ) ;
}
2013-01-03 14:08:10 -08:00
2022-06-17 16:44:17 -07:00
// local
2013-01-03 14:08:10 -08:00
copy = malloc ( sizeof ( E_Notification_Notify ) ) ;
EINA_SAFETY_ON_NULL_RETURN_VAL ( copy , EINA_FALSE ) ;
memcpy ( copy , notify , sizeof ( E_Notification_Notify ) ) ;
copy - > app_name = eina_stringshare_add ( notify - > app_name ) ;
copy - > body = eina_stringshare_add ( notify - > body ) ;
2014-07-30 16:18:24 -07:00
copy - > summary = eina_stringshare_add ( notify - > summary ) ;
2013-01-03 14:08:10 -08:00
copy - > icon . icon = eina_stringshare_add ( notify - > icon . icon ) ;
if ( notify - > icon . icon_path )
copy - > icon . icon_path = eina_stringshare_add ( notify - > icon . icon_path ) ;
id = n_data - > notify_cb ( n_data - > data , copy ) ;
2022-06-17 16:44:17 -07:00
if ( cb ) cb ( ( void * ) data , id ) ;
2013-01-03 14:08:10 -08:00
return EINA_TRUE ;
}
2013-01-11 02:34:29 -08:00
2018-01-22 12:13:24 -08:00
E_API Eina_Bool
e_notification_util_send ( const char * summary , const char * body )
{
E_Notification_Notify n ;
memset ( & n , 0 , sizeof ( E_Notification_Notify ) ) ;
n . timeout = 3000 ;
n . summary = summary ;
n . body = body ;
n . urgency = E_NOTIFICATION_NOTIFY_URGENCY_NORMAL ;
return e_notification_client_send ( & n , NULL , NULL ) ;
}