Handle disappearing serial devices
[fw/altos] / aoview / aoview_log.c
1 /*
2  * Copyright © 2009 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 #include "aoview.h"
19
20 #define LOG_DIR_PATH    "/apps/aoview/log_dir"
21 #define DEFAULT_LOG     "AltOS"
22
23 static char *aoview_log_dir;
24 static FILE *aoview_log_file;
25 static int aoview_log_serial;
26 static int aoview_log_sequence;
27 static GtkMessageDialog *log_fail_dialog;
28 static int aoview_log_failed;
29
30 static void
31 aoview_log_save_conf(void)
32 {
33         GConfClient     *gconf_client;
34
35         gconf_client = gconf_client_get_default();
36         if (gconf_client)
37         {
38                 gconf_client_set_string(gconf_client,
39                                         LOG_DIR_PATH,
40                                         aoview_log_dir,
41                                         NULL);
42                 g_object_unref(G_OBJECT(gconf_client));
43         }
44 }
45
46 static void
47 aoview_log_configure(GtkWidget *widget, gpointer data)
48 {
49         GtkFileChooser *chooser = data;
50         aoview_log_dir = gtk_file_chooser_get_filename(chooser);
51         aoview_log_save_conf();
52         gtk_widget_hide(GTK_WIDGET(chooser));
53 }
54
55 void
56 aoview_log_new(void)
57 {
58         if (aoview_log_file) {
59                 fclose(aoview_log_file);
60                 aoview_log_file = NULL;
61         }
62         aoview_log_failed = 0;
63         aoview_state_new();
64 }
65
66 static void
67 aoview_log_new_item(GtkWidget *widget, gpointer data)
68 {
69         aoview_log_new();
70 }
71
72 void
73 aoview_log_set_serial(int serial)
74 {
75         aoview_log_serial = serial;
76 }
77
78 int
79 aoview_log_get_serial(void)
80 {
81         return aoview_log_serial;
82 }
83
84 static void
85 aoview_log_open_failed(char *name)
86 {
87         char    *utf8_file;
88         utf8_file = g_filename_to_utf8(name, -1, NULL, NULL, NULL);
89         if (!utf8_file)
90                 utf8_file = name;
91         gtk_message_dialog_format_secondary_text(log_fail_dialog,
92                                                  "\"%s\"", utf8_file);
93         if (utf8_file != name)
94                 g_free(utf8_file);
95         gtk_dialog_run(GTK_DIALOG(log_fail_dialog));
96         gtk_widget_hide(GTK_WIDGET(log_fail_dialog));
97         aoview_log_failed = 1;
98 }
99
100 static void
101 aoview_log_start(void)
102 {
103         if (!aoview_log_file) {
104                 char            base[50];
105                 struct tm       tm;
106                 time_t          now;
107                 char            *full;
108                 int             r;
109
110                 now = time(NULL);
111                 (void) localtime_r(&now, &tm);
112                 aoview_mkdir(aoview_log_dir);
113                 for (;;) {
114                         sprintf(base, "%04d-%02d-%02d-serial-%03d-flight-%03d.log",
115                                 tm.tm_year + 1900,
116                                 tm.tm_mon + 1,
117                                 tm.tm_mday,
118                                 aoview_log_serial,
119                                 aoview_log_sequence);
120                         full = aoview_fullname(aoview_log_dir, base);
121                         r = access(full, F_OK);
122                         if (r < 0) {
123                                 aoview_log_file = fopen(full, "w");
124                                 if (!aoview_log_file)
125                                         aoview_log_open_failed(full);
126                                 else
127                                         setlinebuf(aoview_log_file);
128                                 free(full);
129                                 break;
130                         }
131                         free (full);
132                         aoview_log_sequence++;
133                 }
134         }
135 }
136
137 void
138 aoview_log_printf(char *format, ...)
139 {
140         va_list ap;
141
142         if (aoview_log_failed)
143                 return;
144         aoview_log_start();
145         va_start(ap, format);
146         vfprintf(aoview_log_file, format, ap);
147         va_end(ap);
148 }
149
150 void
151 aoview_log_init(GladeXML *xml)
152 {
153         GConfClient     *gconf_client;
154         char            *log_dir = NULL;
155         GtkFileChooser  *log_chooser_dialog;
156         GtkWidget       *log_configure_ok;
157         GtkWidget       *log_new;
158
159         g_type_init();
160         gconf_client = gconf_client_get_default();
161         if (gconf_client)
162         {
163                 log_dir = gconf_client_get_string(gconf_client,
164                                                   LOG_DIR_PATH,
165                                                   NULL);
166                 g_object_unref(G_OBJECT(gconf_client));
167         }
168         if (!log_dir) {
169                 aoview_log_dir = aoview_fullname(getenv("HOME"), DEFAULT_LOG);
170                 aoview_log_save_conf();
171         } else {
172                 aoview_log_dir = strdup(log_dir);
173         }
174
175         log_chooser_dialog = GTK_FILE_CHOOSER(glade_xml_get_widget(xml, "log_chooser_dialog"));
176         assert(log_chooser_dialog);
177         gtk_file_chooser_set_filename(log_chooser_dialog, aoview_log_dir);
178
179         log_configure_ok = glade_xml_get_widget(xml, "log_configure_ok");
180         assert(log_configure_ok);
181
182         g_signal_connect(G_OBJECT(log_configure_ok), "clicked",
183                          G_CALLBACK(aoview_log_configure),
184                          log_chooser_dialog);
185
186         log_new = glade_xml_get_widget(xml, "ao_log_new");
187         assert(log_new);
188         g_signal_connect(G_OBJECT(log_new), "activate",
189                          G_CALLBACK(aoview_log_new_item),
190                          NULL);
191
192         log_fail_dialog = GTK_MESSAGE_DIALOG(glade_xml_get_widget(xml, "log_fail_dialog"));
193         assert(log_fail_dialog);
194 }