Add simple post-flight analysis tool (ao-postflight)
[fw/altos] / ao-tools / ao-view / aoview_file.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 char *aoview_file_dir;
21
22 #define ALTOS_DIR_PATH  "/apps/aoview/log_dir"
23 #define DEFAULT_DIR     "AltOS"
24
25 struct aoview_file {
26         char    *ext;
27         FILE    *file;
28         char    *name;
29         int     failed;
30         int     serial;
31         int     sequence;
32 };
33
34 static void
35 aoview_file_save_conf(void)
36 {
37         GConfClient     *gconf_client;
38
39         gconf_client = gconf_client_get_default();
40         if (gconf_client)
41         {
42                 gconf_client_set_string(gconf_client,
43                                         ALTOS_DIR_PATH,
44                                         aoview_file_dir,
45                                         NULL);
46                 g_object_unref(G_OBJECT(gconf_client));
47         }
48 }
49
50 static void
51 aoview_file_configure(GtkWidget *widget, gpointer data)
52 {
53         GtkFileChooser *chooser = data;
54         aoview_file_dir = gtk_file_chooser_get_filename(chooser);
55         aoview_file_save_conf();
56         gtk_widget_hide(GTK_WIDGET(chooser));
57 }
58
59 void
60 aoview_file_finish(struct aoview_file *file)
61 {
62         if (file->file) {
63                 fclose(file->file);
64                 file->file = NULL;
65                 free(file->name);
66                 file->name = NULL;
67         }
68         file->failed = 0;
69 }
70
71 const char *
72 aoview_file_name(struct aoview_file *file)
73 {
74         return file->name;
75 }
76
77 static GtkMessageDialog *file_fail_dialog;
78
79 static void
80 aoview_file_open_failed(char *name)
81 {
82         char    *utf8_file;
83         utf8_file = g_filename_to_utf8(name, -1, NULL, NULL, NULL);
84         if (!utf8_file)
85                 utf8_file = name;
86         gtk_message_dialog_format_secondary_text(file_fail_dialog,
87                                                  "\"%s\"", utf8_file);
88         if (utf8_file != name)
89                 g_free(utf8_file);
90         gtk_widget_show(GTK_WIDGET(file_fail_dialog));
91 }
92
93 gboolean
94 aoview_file_start(struct aoview_file *file)
95 {
96         char            base[50];
97         struct tm       tm;
98         time_t          now;
99         char            *full;
100         int             r;
101
102         if (file->file)
103                 return TRUE;
104
105         if (file->failed)
106                 return FALSE;
107
108         now = time(NULL);
109         (void) localtime_r(&now, &tm);
110         aoview_mkdir(aoview_file_dir);
111         for (;;) {
112                 snprintf(base, sizeof (base), "%04d-%02d-%02d-serial-%03d-flight-%03d.%s",
113                         tm.tm_year + 1900,
114                         tm.tm_mon + 1,
115                         tm.tm_mday,
116                         file->serial,
117                         file->sequence,
118                         file->ext);
119                 full = aoview_fullname(aoview_file_dir, base);
120                 r = access(full, F_OK);
121                 if (r < 0) {
122                         file->file = fopen(full, "w");
123                         if (!file->file) {
124                                 aoview_file_open_failed(full);
125                                 free(full);
126                                 file->failed = 1;
127                                 return FALSE;
128                         } else {
129                                 setlinebuf(file->file);
130                                 file->name = full;
131                                 return TRUE;
132                         }
133                 }
134                 free(full);
135                 file->sequence++;
136         }
137 }
138
139 void
140 aoview_file_vprintf(struct aoview_file *file, char *format, va_list ap)
141 {
142         if (!aoview_file_start(file))
143                 return;
144         vfprintf(file->file, format, ap);
145 }
146
147 void
148 aoview_file_printf(struct aoview_file *file, char *format, ...)
149 {
150         va_list ap;
151
152         va_start(ap, format);
153         aoview_file_vprintf(file, format, ap);
154         va_end(ap);
155 }
156
157 struct aoview_file *
158 aoview_file_new(char *ext)
159 {
160         struct aoview_file      *file;
161
162         file = calloc (1, sizeof (struct aoview_file));
163         if (!file)
164                 return NULL;
165         file->ext = strdup(ext);
166         if (!file->ext) {
167                 free(file);
168                 return NULL;
169         }
170         return file;
171 }
172
173 void
174 aoview_file_destroy(struct aoview_file *file)
175 {
176         if (file->file)
177                 fclose(file->file);
178         if (file->name)
179                 free(file->name);
180         free(file->ext);
181         free(file);
182 }
183
184 void
185 aoview_file_set_serial(struct aoview_file *file, int serial)
186 {
187         if (serial != file->serial)
188                 aoview_file_finish(file);
189         file->serial = serial;
190 }
191
192 int
193 aoview_file_get_serial(struct aoview_file *file)
194 {
195         return file->serial;
196 }
197
198 void
199 aoview_file_init(GladeXML *xml)
200 {
201         GConfClient     *gconf_client;
202         char            *file_dir = NULL;
203         GtkFileChooser  *file_chooser_dialog;
204         GtkWidget       *file_configure_ok;
205
206         g_type_init();
207         gconf_client = gconf_client_get_default();
208         if (gconf_client)
209         {
210                 file_dir = gconf_client_get_string(gconf_client,
211                                                    ALTOS_DIR_PATH,
212                                                    NULL);
213                 g_object_unref(G_OBJECT(gconf_client));
214         }
215         if (!file_dir) {
216                 aoview_file_dir = aoview_fullname(getenv("HOME"), DEFAULT_DIR);
217                 aoview_file_save_conf();
218         } else {
219                 aoview_file_dir = strdup(file_dir);
220         }
221
222         file_chooser_dialog = GTK_FILE_CHOOSER(glade_xml_get_widget(xml, "file_chooser_dialog"));
223         assert(file_chooser_dialog);
224         gtk_file_chooser_set_filename(file_chooser_dialog, aoview_file_dir);
225
226         file_configure_ok = glade_xml_get_widget(xml, "file_configure_ok");
227         assert(file_configure_ok);
228
229         g_signal_connect(G_OBJECT(file_configure_ok), "clicked",
230                          G_CALLBACK(aoview_file_configure),
231                          file_chooser_dialog);
232
233
234         file_fail_dialog = GTK_MESSAGE_DIALOG(glade_xml_get_widget(xml, "file_fail_dialog"));
235         assert(file_fail_dialog);
236 }