3
* Copyright (C) 2004-2007 Xin Zhen
4
* Copyright (C) 2008 Daniele Napolitano
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version 2
9
* of the License, or (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22
#include "ircptray_main.h"
25
#include <libnotify/notification.h>
26
#include <libnotify/notify.h>
29
#include <glib/gi18n-lib.h>
30
#include "ircptray_trayicon.h"
31
#include "resources.h"
34
#include "irda_misc.h"
36
/* Discover interval in seconds */
37
#define DISCOVERER_POLL_INTERVAL 3
38
/* user config path */
39
#define CONFIG_FILENAME "/ircp-tray.conf"
41
GtkStatusIcon* AppTrayIcon;
43
static gboolean check_irda_config()
46
if (g_file_test("/var/run/irattach.pid", G_FILE_TEST_EXISTS))
49
g_printerr("WW: /var/run/irattach.pid not found, assumed irattach not running");
60
fp = fopen("/etc/default/irda-utils", "r");
64
while(fgets(data, 15, fp))
65
if(g_str_has_prefix (data, "ENABLE") == TRUE) break;
67
data = g_strstrip(data);
68
v1 = g_strsplit(data, "=", 2);
69
v2 = g_strsplit(v1[1], "\"", 3);
70
result = strncmp("false", v2[1], 5 );
74
printf("IrDA enabled: %s\n", v2[1]);
80
if(result == 0) return FALSE;
86
void version_onclick(GtkMenuItem *menuitem, gpointer user_data)
90
"Xin Zhen <xinzhen@pub.minidns.net>",
91
"Daniele Napolitano <dnax88@gmail.com>",
100
"Icon design: Jakub Steiner <jimmac@ximian.com>",
101
"Animation: Dieter Vanderfaeillie <dieter.vanderfaeillie@gmail.com>",
105
/* Feel free to put your names here translators :-) */
106
char* translators = _("translator-credits");
108
gtk_show_about_dialog(NULL,
111
"translator-credits", strcmp("translator-credits", translators) ? translators : NULL,
112
"comments", _("A utility for IrDA OBEX beaming and receiving"),
113
"copyright", "Copyright © 2004-2007 Xin Zhen \"LoneStar\"\nCopyright © 2008-2010 Daniele Napolitano \"DnaX\"",
115
"website", "http://launchpad.net/ircp-tray",
116
"logo-icon-name", MAIN_ICON,
121
/* Get last save directory from user config file */
122
char* config_get_lastsavedir()
124
char* lastsavedir = NULL;
125
char* configfilename;
128
configfilename = g_strconcat (g_get_user_config_dir(),
132
config = g_key_file_new();
133
g_key_file_load_from_file(config, configfilename,
134
G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, NULL);
135
lastsavedir = g_key_file_get_string(config, "General", "LastSaveDir",
137
g_key_file_free(config);
138
g_free(configfilename);
143
/* Save last save directory from user config file */
144
void config_set_lastsavedir(char* dir)
146
char* configfilename;
151
configfilename = g_strconcat (g_get_user_config_dir(),
154
g_print("%s\n", configfilename);
155
config = g_key_file_new();
156
g_key_file_load_from_file(config, configfilename,
157
G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, NULL);
158
g_key_file_set_string(config, "General", "LastSaveDir", dir);
160
configstr = g_key_file_to_data(config, NULL, NULL);
162
configfile = fopen(configfilename, "w");
163
fprintf(configfile, configstr, NULL);
167
g_free(configfilename);
168
g_key_file_free(config);
175
char filename[] = "/.ircp-tray_log";
177
logfile = g_malloc(strlen(g_get_home_dir())+strlen(filename)+1);
178
g_sprintf(logfile, "%s%s", g_get_home_dir(), filename);
182
void log_file(const char* message)
187
time_t tm = time(NULL);
189
printf("%s\n", message);
190
strftime(tmstr, 20, "%x %X", localtime(&tm));
192
logfile = get_log_path();
194
fp = fopen(logfile, "a");
196
fprintf(fp, "[%s] %s\n", tmstr, message);
202
static char *discoverer_name;
203
static int discoverer_hints[2];
205
/* Do some things on device discovered */
207
gui_update_on_discovery (gchar *device_name)
209
/* Refresh tray icon */
210
trayicon_set_icon(ICON_TRAY);
212
/* Update icon tray tooltip */
215
tooltip_msg = g_strdup_printf (_("Infrared File Transfer: %s"), device_name);
216
trayicon_set_tooltip_text(tooltip_msg);
219
/* Activate device info menù item */
220
trayicon_set_info_menuitem_sensitive(TRUE);
223
/* Do some things on device disappeared */
225
gui_update_on_disappearing (guint num_devices)
227
/* Refresh tray icon */
228
trayicon_set_icon(ICON_TRAY_INACTIVE);
230
/* Update icon tray tooltip */
231
trayicon_set_tooltip_text(_("Infrared File Transfer") );
233
/* Disable device info menù item on zero devices */
234
if ( num_devices <= 0 )
235
trayicon_set_info_menuitem_sensitive(FALSE);
239
/* Send notify on device discovered */
241
notify_on_discovering (gchar *device_name, gchar *icon )
243
NotifyNotification *notification = NULL;
246
notify_msg = g_strdup_printf( _("Remote device discovered: %s"),
249
notification = notify_notification_new (g_get_application_name(),
253
if (notification == NULL) {
254
g_warning("failed to setup notification");
258
notify_notification_attach_to_status_icon (notification, AppTrayIcon);
260
if (!notify_notification_show (notification, NULL))
261
g_warning("failed to send notification");
263
/* destroy intantly if there isn't actions */
264
g_object_unref(G_OBJECT(notification));
268
/* Send notify on device disappeared */
270
notify_on_disappearing (gchar *device_name, gchar *icon )
272
NotifyNotification *notification = NULL;
275
notify_msg = g_strdup_printf( _("Remote device %s disappeared"),
278
notification = notify_notification_new (g_get_application_name(),
283
if (notification != NULL) {
284
notify_notification_attach_to_status_icon (notification, AppTrayIcon);
286
if (!notify_notification_show (notification, NULL))
287
g_warning("failed to send notification\n");
288
g_object_unref(G_OBJECT(notification));
291
g_warning("failed to setup notification");
298
/* Function called each X seconds that detect device discovered
299
* and disappeared. Then send notification and update GUI. */
300
static gboolean discover_do(gpointer data)
304
dev_info *device, *device2;
308
list = irda_discover_devices();
309
list_length = g_list_length(list);
311
/* Check for added devices */
312
for(i = 0; i < list_length; i++)
314
device = g_list_nth_data(list, i);
316
if(DevicesList == NULL)
318
/* Device discovered */
319
g_print("* Device discovered: %s [0x%08x]\n",
320
device->name, device->daddr);
322
notify_on_discovering (device->name, device->icon);
323
gui_update_on_discovery (device->name);
325
if(device->hints[1] & 0x20) {
327
g_free(discoverer_name);
328
discoverer_name = g_strdup(device->name);
329
discoverer_hints[0] = device->hints[0];
330
discoverer_hints[1] = device->hints[1];
335
for(c = 0; c < NumDevices; c++)
337
device2 = g_list_nth_data(DevicesList, c);
339
if( device->daddr == device2->daddr ) {
347
/* Device discovered */
350
g_print("* Device discovered: %s [0x%08x]\n",
351
device->name, device->daddr);
353
notify_on_discovering (device->name, device->icon);
354
gui_update_on_discovery (device->name);
356
if(device->hints[1] & 0x20) {
358
g_free(discoverer_name);
359
discoverer_name = g_strdup(device->name);
360
discoverer_hints[0] = device->hints[0];
361
discoverer_hints[1] = device->hints[1];
367
/* Check for removed devices */
368
for(i = 0; i < NumDevices; i++)
370
device = g_list_nth_data(DevicesList, i);
374
for(c = 0; c < list_length; c++)
376
device2 = g_list_nth_data(list, c);
378
if(device->daddr == device2->daddr)
385
/* Device disappeared */
388
g_print("* Device disappeared: %s [0x%08x]\n",
389
device->name, device->daddr);
391
notify_on_disappearing (device->name, device->icon);
392
gui_update_on_disappearing (list_length);
394
if(g_strcmp0(discoverer_name, device->name) == 0) {
395
//discoverer_name = NULL;
396
discoverer_hints[0] = 0;
397
discoverer_hints[1] = 0;
403
free_devices_list (DevicesList);
405
NumDevices = list_length;
407
g_timeout_add_seconds(DISCOVERER_POLL_INTERVAL,
414
static void device_discovery_start()
416
g_print("* Start polling of devices in range, interval %d seconds\n",
417
DISCOVERER_POLL_INTERVAL);
421
char* discoverer_get_name()
423
return discoverer_name;
426
int* discoverer_get_hints()
428
return discoverer_hints;
431
int discoverer_is_in_range()
433
return NumDevices > 0;
437
on_dialog_response (GtkDialog *dialog, gint response, gpointer ok_handler_data)
439
if (response == GTK_RESPONSE_CLOSE) {
440
gtk_widget_destroy (GTK_WIDGET (dialog));
442
DEBUG(5,"Dialog destroyed\n");
447
show_device_info_cb( void *data )
460
gchar *labels[] = {_("<b>Hints</b>"),
478
if ( NumDevices <= 0 )
481
info = gtk_dialog_new ();
484
gtk_window_set_title (GTK_WINDOW (info), _("Information"));
485
gtk_window_set_resizable( GTK_WINDOW (info), FALSE );
488
//GdkScreen *screen = gtk_widget_get_screen(info);
489
//GdkColormap *colormap = gdk_screen_get_rgba_colormap (screen);
492
// gtk_widget_set_default_colormap(colormap);
494
gtk_window_set_destroy_with_parent (GTK_WINDOW (info), TRUE);
495
gtk_dialog_set_default_response (GTK_DIALOG (info), GTK_RESPONSE_CLOSE);
497
vbox1 = gtk_dialog_get_content_area (GTK_DIALOG (info));
498
gtk_widget_show (vbox1);
500
table1 = gtk_table_new (15, NumDevices+1, TRUE);
501
gtk_widget_show (table1);
502
gtk_box_pack_start (GTK_BOX (vbox1), table1, TRUE, TRUE, 0);
506
while ( labels[i] ) {
507
label1 = gtk_label_new (_(labels[i]));
508
gtk_widget_show (label1);
509
gtk_table_attach (GTK_TABLE (table1), label1, 0, 1, i, i+1,
510
(GtkAttachOptions) (GTK_FILL),
511
(GtkAttachOptions) (0), 5, 0);
512
gtk_label_set_justify (GTK_LABEL (label1), GTK_JUSTIFY_LEFT);
513
gtk_label_set_use_markup (GTK_LABEL (label1), TRUE);
514
gtk_misc_set_alignment (GTK_MISC (label1), 0, 0.5);
518
/* Adding checkboxes */
523
dev = (dev_info*) devs->data;
525
label1 = gtk_label_new( dev->name );
526
gtk_widget_show (label1);
527
gtk_table_attach (GTK_TABLE (table1), label1, i+1, i+2, 0, 1,
528
(GtkAttachOptions) (GTK_FILL),
529
(GtkAttachOptions) (0), 5, 0);
530
gtk_label_set_justify (GTK_LABEL (label1), GTK_JUSTIFY_LEFT);
531
gtk_misc_set_alignment (GTK_MISC (label1), 0, 0.5);
534
while ( labels[y] ) {
535
ck1 = gtk_check_button_new();
536
gtk_widget_set_can_focus (ck1, FALSE);
537
gtk_widget_set_sensitive (ck1, FALSE);
539
if ( (y <= 8) && (dev->hints[0] & 1<<(y-1)) )
540
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ck1), 1 );
542
if ( (y > 7) && (dev->hints[1] & 1<<(y-9)) )
543
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(ck1), 1 );
545
gtk_widget_show (ck1);
546
gtk_table_attach (GTK_TABLE (table1), ck1, i+1, i+2, y, y+1,
547
(GtkAttachOptions) (GTK_FILL),
548
(GtkAttachOptions) (0), 5, 0);
555
/* Create close button */
556
aa1 = gtk_dialog_get_action_area (GTK_DIALOG (info));
557
gtk_widget_show (aa1);
558
gtk_button_box_set_layout (GTK_BUTTON_BOX (aa1), GTK_BUTTONBOX_END);
560
close = gtk_button_new_from_stock ("gtk-close");
561
gtk_widget_show (close);
562
gtk_dialog_add_action_widget (GTK_DIALOG (info), close, GTK_RESPONSE_CLOSE);
563
gtk_widget_set_can_default (close, TRUE);
565
g_signal_connect (GTK_OBJECT (info), "response",
566
G_CALLBACK (on_dialog_response),
569
gtk_widget_show(info);
574
int clean_log_file( GtkWidget* w, gpointer data )
576
GtkTextBuffer *buffer = data;
577
GtkTextIter *start_iter, *end_iter;
580
logfile = get_log_path();
582
if(g_remove (logfile))
584
g_print("Deleted log file: %s\n", logfile);
585
gtk_text_buffer_set_text (buffer, "", -1);
597
on_dialog_log_response(GtkDialog *dialog, gint response, gpointer ok_handler_data)
599
if (response == GTK_RESPONSE_CLOSE) {
600
gtk_widget_destroy (GTK_WIDGET (dialog));
602
DEBUG(5,"Log Dialog destroyed\n");
606
GtkWidget* show_log_file( void *data )
608
GtkWidget *dialog, *button_clear, *button_close;
609
GtkWidget *view, *scroll, *frame;
610
GtkTextBuffer *buffer;
617
logfile = get_log_path();
619
content = g_malloc0(64 * 1024);
621
fp = fopen(logfile, "r");
623
len = fread(content, 1, 64 * 1024, fp);
628
dialog = gtk_dialog_new();
629
gtk_window_set_title (GTK_WINDOW (dialog), _("History"));
630
gtk_dialog_set_has_separator(GTK_DIALOG (dialog), FALSE);
631
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
632
g_object_set (dialog, "border_width", 5, NULL);
635
GdkScreen *screen = gtk_widget_get_screen(dialog);
636
GdkColormap *colormap = gdk_screen_get_rgba_colormap (screen);
639
gtk_widget_set_default_colormap(colormap);
643
frame = gtk_frame_new( _("<b>Transfers History</b>") );
644
gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_NONE);
645
gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), frame);
648
gtk_label_set_use_markup( GTK_LABEL( gtk_frame_get_label_widget (GTK_FRAME(frame))), TRUE );
651
scroll = gtk_scrolled_window_new(NULL, NULL);
652
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (scroll),
653
GTK_POLICY_AUTOMATIC,
654
GTK_POLICY_AUTOMATIC);
655
gtk_container_add (GTK_CONTAINER (frame), scroll);
656
gtk_widget_set_size_request(scroll, 400, 200);
659
view = gtk_text_view_new ();
660
gtk_text_view_set_editable( GTK_TEXT_VIEW (view), FALSE );
661
gtk_text_view_set_cursor_visible( GTK_TEXT_VIEW (view), FALSE );
662
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW (scroll), view);
665
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
666
gtk_text_buffer_set_text (buffer, content, len);
669
button_clear = gtk_button_new_from_stock( GTK_STOCK_CLEAR );
670
gtk_container_add (GTK_CONTAINER (gtk_dialog_get_action_area (GTK_DIALOG (dialog))), button_clear);
672
button_close = gtk_button_new_from_stock( GTK_STOCK_CLOSE );
673
gtk_dialog_add_action_widget(GTK_DIALOG (dialog), button_close, GTK_RESPONSE_CLOSE);
675
g_signal_connect (GTK_OBJECT (dialog), "response",
676
G_CALLBACK (on_dialog_log_response),
679
g_signal_connect(G_OBJECT (button_clear),
681
G_CALLBACK (clean_log_file),
684
gtk_widget_show_all(dialog);
697
if(!irda_check()) //no irda support
701
g_printerr("EE: irda kernel module not loaded, quit");
703
dialog = gtk_message_dialog_new(NULL,
707
_("You don't seem to have IrDA enabled in your kernel, quit."),
710
gtk_dialog_run(GTK_DIALOG(dialog));
715
if( !check_irda_config() )
719
dialog = gtk_message_dialog_new(NULL,
723
_("IrDA service not started!"),
726
gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(dialog),
727
_("<i>You must edit <b>\"/etc/default/irda-utils\"</b> and set irattach to start it on boot.\n\nOtherwise, try typing in terminal:\n\n\"sudo irattach /dev/ttyS1 -s\"\n\nRead the irattach manual for more info.\n\n<span color=\"#f00000\" style=\"normal\"><b>%s will not be able to work.</b></span></i>"), g_get_application_name());
729
gtk_window_set_title (GTK_WINDOW(dialog), "Ircp Tray");
730
gtk_dialog_run(GTK_DIALOG(dialog));
731
gtk_widget_destroy(dialog);
734
notify_init(PACKAGE);
736
AppTrayIcon = trayicon_init();
738
recvfile_listen(TRUE);
740
device_discovery_start();