Make file handling more general so it can be reused.
authorKeith Packard <keithp@keithp.com>
Wed, 20 May 2009 16:44:55 +0000 (09:44 -0700)
committerKeith Packard <keithp@keithp.com>
Wed, 20 May 2009 16:44:55 +0000 (09:44 -0700)
The log file handling stuff will be useful for saving eeprom data, so pull
it out of the real-time log handling code and make a general interface.

Signed-off-by: Keith Packard <keithp@keithp.com>
aoview/Makefile
aoview/aoview.glade
aoview/aoview.h
aoview/aoview_file.c [new file with mode: 0644]
aoview/aoview_log.c
aoview/aoview_main.c

index a2878b0e6d93d8a436e220c3a0468001d60340eb..ca636065a37c6e4c58c012c645855f6fc0bb3d3b 100644 (file)
@@ -17,7 +17,8 @@ SRC = \
        aoview_convert.c \
        aoview_log.c \
        aoview_table.c \
-       aoview_util.c
+       aoview_util.c \
+       aoview_file.c
 
 INC = \
        aoview.h
index 74485ec5626340f28d384e983d511506e0169ccb..eb7f108b7792016d47f26e2f81d8707c0689f17a 100644 (file)
                   <widget class="GtkMenu" id="menu5">
                     <property name="visible">True</property>
                     <child>
-                      <widget class="GtkImageMenuItem" id="ao_log_new">
+                      <widget class="GtkImageMenuItem" id="log_new">
                         <property name="label" translatable="yes">_New log</property>
                         <property name="visible">True</property>
                         <property name="use_underline">True</property>
                       </widget>
                     </child>
                     <child>
-                      <widget class="GtkImageMenuItem" id="ao_log_configure">
+                      <widget class="GtkImageMenuItem" id="file_configure">
                         <property name="label" translatable="yes">_Configure Log</property>
                         <property name="visible">True</property>
                         <property name="use_underline">True</property>
                         <property name="use_stock">False</property>
-                        <signal name="activate" handler="gtk_widget_show" object="log_chooser_dialog" after="yes"/>
+                        <signal name="activate" handler="gtk_widget_show" object="file_chooser_dialog" after="yes"/>
                         <child internal-child="image">
                           <widget class="GtkImage" id="image4">
                             <property name="visible">True</property>
       </widget>
     </child>
   </widget>
-  <widget class="GtkFileChooserDialog" id="log_chooser_dialog">
+  <widget class="GtkFileChooserDialog" id="file_chooser_dialog">
     <property name="border_width">5</property>
     <property name="title" translatable="yes">Configure Log Directory</property>
     <property name="type_hint">dialog</property>
             <property name="visible">True</property>
             <property name="layout_style">end</property>
             <child>
-              <widget class="GtkButton" id="log_configure_cancel">
+              <widget class="GtkButton" id="file_configure_cancel">
                 <property name="label" translatable="yes">gtk-cancel</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
                 <property name="use_stock">True</property>
-                <signal name="clicked" handler="gtk_widget_hide" object="log_chooser_dialog"/>
+                <signal name="clicked" handler="gtk_widget_hide" object="file_chooser_dialog"/>
               </widget>
               <packing>
                 <property name="expand">False</property>
               </packing>
             </child>
             <child>
-              <widget class="GtkButton" id="log_configure_ok">
+              <widget class="GtkButton" id="file_configure_ok">
                 <property name="label" translatable="yes">gtk-ok</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
       </widget>
     </child>
   </widget>
-  <widget class="GtkMessageDialog" id="log_fail_dialog">
+  <widget class="GtkMessageDialog" id="file_fail_dialog">
     <property name="border_width">5</property>
     <property name="title" translatable="yes">Failed to create log</property>
     <property name="type_hint">normal</property>
index 4abbde88839ca0c8bdd4420dc3ff0c62824b9cde..7b5f0de5b7c5dd2ced0639032550ee4796721593 100644 (file)
@@ -170,4 +170,33 @@ aoview_table_init(GladeXML *xml);
 void
 aoview_table_clear(void);
 
+struct aoview_file;
+
+void
+aoview_file_finish(struct aoview_file *file);
+
+gboolean
+aoview_file_start(struct aoview_file *file);
+
+void
+aoview_file_set_serial(struct aoview_file *file, int serial);
+
+int
+aoview_file_get_serial(struct aoview_file *file);
+
+void
+aoview_file_printf(struct aoview_file *file, char *format, ...);
+
+void
+aoview_file_vprintf(struct aoview_file *file, char *format, va_list ap);
+
+struct aoview_file *
+aoview_file_new(char *ext);
+
+void
+aoview_file_destroy(struct aoview_file *file);
+
+void
+aoview_file_init(GladeXML *xml);
+
 #endif /* _AOVIEW_H_ */
diff --git a/aoview/aoview_file.c b/aoview/aoview_file.c
new file mode 100644 (file)
index 0000000..d86d587
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "aoview.h"
+
+static char *aoview_file_dir;
+
+#define ALTOS_DIR_PATH "/apps/aoview/log_dir"
+#define DEFAULT_DIR    "AltOS"
+
+struct aoview_file {
+       char    *ext;
+       FILE    *file;
+       char    *name;
+       int     failed;
+       int     serial;
+       int     sequence;
+};
+
+static void
+aoview_file_save_conf(void)
+{
+       GConfClient     *gconf_client;
+
+       gconf_client = gconf_client_get_default();
+       if (gconf_client)
+       {
+               gconf_client_set_string(gconf_client,
+                                       ALTOS_DIR_PATH,
+                                       aoview_file_dir,
+                                       NULL);
+               g_object_unref(G_OBJECT(gconf_client));
+       }
+}
+
+static void
+aoview_file_configure(GtkWidget *widget, gpointer data)
+{
+       GtkFileChooser *chooser = data;
+       aoview_file_dir = gtk_file_chooser_get_filename(chooser);
+       aoview_file_save_conf();
+       gtk_widget_hide(GTK_WIDGET(chooser));
+}
+
+void
+aoview_file_finish(struct aoview_file *file)
+{
+       if (file->file) {
+               fclose(file->file);
+               file->file = NULL;
+               free(file->name);
+               file->name = NULL;
+       }
+       file->failed = 0;
+}
+
+static GtkMessageDialog *file_fail_dialog;
+
+static void
+aoview_file_open_failed(char *name)
+{
+       char    *utf8_file;
+       utf8_file = g_filename_to_utf8(name, -1, NULL, NULL, NULL);
+       if (!utf8_file)
+               utf8_file = name;
+       gtk_message_dialog_format_secondary_text(file_fail_dialog,
+                                                "\"%s\"", utf8_file);
+       if (utf8_file != name)
+               g_free(utf8_file);
+       gtk_widget_show(GTK_WIDGET(file_fail_dialog));
+}
+
+gboolean
+aoview_file_start(struct aoview_file *file)
+{
+       char            base[50];
+       struct tm       tm;
+       time_t          now;
+       char            *full;
+       int             r;
+
+       if (file->file)
+               return TRUE;
+
+       if (file->failed)
+               return FALSE;
+
+       now = time(NULL);
+       (void) localtime_r(&now, &tm);
+       aoview_mkdir(aoview_file_dir);
+       for (;;) {
+               snprintf(base, sizeof (base), "%04d-%02d-%02d-serial-%03d-flight-%03d.%s",
+                       tm.tm_year + 1900,
+                       tm.tm_mon + 1,
+                       tm.tm_mday,
+                       file->serial,
+                       file->sequence,
+                       file->ext);
+               full = aoview_fullname(aoview_file_dir, base);
+               r = access(full, F_OK);
+               if (r < 0) {
+                       file->file = fopen(full, "w");
+                       if (!file->file) {
+                               aoview_file_open_failed(full);
+                               free(full);
+                               file->failed = 1;
+                               return FALSE;
+                       } else {
+                               setlinebuf(file->file);
+                               file->name = full;
+                               return TRUE;
+                       }
+               }
+               free(full);
+               file->sequence++;
+       }
+}
+
+void
+aoview_file_vprintf(struct aoview_file *file, char *format, va_list ap)
+{
+       if (!aoview_file_start(file))
+               return;
+       vfprintf(file->file, format, ap);
+}
+
+void
+aoview_file_printf(struct aoview_file *file, char *format, ...)
+{
+       va_list ap;
+
+       va_start(ap, format);
+       aoview_file_vprintf(file, format, ap);
+       va_end(ap);
+}
+
+struct aoview_file *
+aoview_file_new(char *ext)
+{
+       struct aoview_file      *file;
+
+       file = calloc (1, sizeof (struct aoview_file));
+       if (!file)
+               return NULL;
+       file->ext = strdup(ext);
+       if (!file->ext) {
+               free(file);
+               return NULL;
+       }
+       return file;
+}
+
+void
+aoview_file_destroy(struct aoview_file *file)
+{
+       if (file->file)
+               fclose(file->file);
+       if (file->name)
+               free(file->name);
+       free(file->ext);
+       free(file);
+}
+
+void
+aoview_file_set_serial(struct aoview_file *file, int serial)
+{
+       if (serial != file->serial)
+               aoview_file_finish(file);
+       file->serial = serial;
+}
+
+int
+aoview_file_get_serial(struct aoview_file *file)
+{
+       return file->serial;
+}
+
+void
+aoview_file_init(GladeXML *xml)
+{
+       GConfClient     *gconf_client;
+       char            *file_dir = NULL;
+       GtkFileChooser  *file_chooser_dialog;
+       GtkWidget       *file_configure_ok;
+
+       g_type_init();
+       gconf_client = gconf_client_get_default();
+       if (gconf_client)
+       {
+               file_dir = gconf_client_get_string(gconf_client,
+                                                  ALTOS_DIR_PATH,
+                                                  NULL);
+               g_object_unref(G_OBJECT(gconf_client));
+       }
+       if (!file_dir) {
+               aoview_file_dir = aoview_fullname(getenv("HOME"), DEFAULT_DIR);
+               aoview_file_save_conf();
+       } else {
+               aoview_file_dir = strdup(file_dir);
+       }
+
+       file_chooser_dialog = GTK_FILE_CHOOSER(glade_xml_get_widget(xml, "file_chooser_dialog"));
+       assert(file_chooser_dialog);
+       gtk_file_chooser_set_filename(file_chooser_dialog, aoview_file_dir);
+
+       file_configure_ok = glade_xml_get_widget(xml, "file_configure_ok");
+       assert(file_configure_ok);
+
+       g_signal_connect(G_OBJECT(file_configure_ok), "clicked",
+                        G_CALLBACK(aoview_file_configure),
+                        file_chooser_dialog);
+
+
+       file_fail_dialog = GTK_MESSAGE_DIALOG(glade_xml_get_widget(xml, "file_fail_dialog"));
+       assert(file_fail_dialog);
+}
index 0afdb64e680168cc20fbdce0eec943d1288febd6..2f2b95608fcd86f2b7c6d67d8009226936e4ba0f 100644 (file)
 
 #include "aoview.h"
 
-#define LOG_DIR_PATH   "/apps/aoview/log_dir"
-#define DEFAULT_LOG    "AltOS"
-
-static char *aoview_log_dir;
-static FILE *aoview_log_file;
-static int aoview_log_serial;
-static int aoview_log_sequence;
-static GtkMessageDialog *log_fail_dialog;
-static int aoview_log_failed;
-
-static void
-aoview_log_save_conf(void)
-{
-       GConfClient     *gconf_client;
-
-       gconf_client = gconf_client_get_default();
-       if (gconf_client)
-       {
-               gconf_client_set_string(gconf_client,
-                                       LOG_DIR_PATH,
-                                       aoview_log_dir,
-                                       NULL);
-               g_object_unref(G_OBJECT(gconf_client));
-       }
-}
-
-static void
-aoview_log_configure(GtkWidget *widget, gpointer data)
-{
-       GtkFileChooser *chooser = data;
-       aoview_log_dir = gtk_file_chooser_get_filename(chooser);
-       aoview_log_save_conf();
-       gtk_widget_hide(GTK_WIDGET(chooser));
-}
+static struct aoview_file      *aoview_log;
 
 void
 aoview_log_new(void)
 {
-       if (aoview_log_file) {
-               fclose(aoview_log_file);
-               aoview_log_file = NULL;
-       }
-       aoview_log_failed = 0;
+       aoview_file_finish(aoview_log);
        aoview_state_new();
 }
 
-static void
-aoview_log_new_item(GtkWidget *widget, gpointer data)
-{
-       aoview_log_new();
-}
-
 void
 aoview_log_set_serial(int serial)
 {
-       aoview_log_serial = serial;
+       aoview_file_set_serial(aoview_log, serial);
 }
 
 int
 aoview_log_get_serial(void)
 {
-       return aoview_log_serial;
-}
-
-static void
-aoview_log_open_failed(char *name)
-{
-       char    *utf8_file;
-       utf8_file = g_filename_to_utf8(name, -1, NULL, NULL, NULL);
-       if (!utf8_file)
-               utf8_file = name;
-       gtk_message_dialog_format_secondary_text(log_fail_dialog,
-                                                "\"%s\"", utf8_file);
-       if (utf8_file != name)
-               g_free(utf8_file);
-       gtk_dialog_run(GTK_DIALOG(log_fail_dialog));
-       gtk_widget_hide(GTK_WIDGET(log_fail_dialog));
-       aoview_log_failed = 1;
-}
-
-static void
-aoview_log_start(void)
-{
-       if (!aoview_log_file) {
-               char            base[50];
-               struct tm       tm;
-               time_t          now;
-               char            *full;
-               int             r;
-
-               now = time(NULL);
-               (void) localtime_r(&now, &tm);
-               aoview_mkdir(aoview_log_dir);
-               for (;;) {
-                       sprintf(base, "%04d-%02d-%02d-serial-%03d-flight-%03d.log",
-                               tm.tm_year + 1900,
-                               tm.tm_mon + 1,
-                               tm.tm_mday,
-                               aoview_log_serial,
-                               aoview_log_sequence);
-                       full = aoview_fullname(aoview_log_dir, base);
-                       r = access(full, F_OK);
-                       if (r < 0) {
-                               aoview_log_file = fopen(full, "w");
-                               if (!aoview_log_file)
-                                       aoview_log_open_failed(full);
-                               else
-                                       setlinebuf(aoview_log_file);
-                               free(full);
-                               break;
-                       }
-                       free (full);
-                       aoview_log_sequence++;
-               }
-       }
+       return aoview_file_get_serial(aoview_log);
 }
 
 void
@@ -139,56 +43,28 @@ aoview_log_printf(char *format, ...)
 {
        va_list ap;
 
-       if (aoview_log_failed)
-               return;
-       aoview_log_start();
        va_start(ap, format);
-       vfprintf(aoview_log_file, format, ap);
+       aoview_file_vprintf(aoview_log, format, ap);
        va_end(ap);
 }
 
+static void
+aoview_log_new_item(GtkWidget *widget, gpointer data)
+{
+       aoview_file_finish(aoview_log);
+}
+
 void
 aoview_log_init(GladeXML *xml)
 {
-       GConfClient     *gconf_client;
-       char            *log_dir = NULL;
-       GtkFileChooser  *log_chooser_dialog;
-       GtkWidget       *log_configure_ok;
        GtkWidget       *log_new;
 
-       g_type_init();
-       gconf_client = gconf_client_get_default();
-       if (gconf_client)
-       {
-               log_dir = gconf_client_get_string(gconf_client,
-                                                 LOG_DIR_PATH,
-                                                 NULL);
-               g_object_unref(G_OBJECT(gconf_client));
-       }
-       if (!log_dir) {
-               aoview_log_dir = aoview_fullname(getenv("HOME"), DEFAULT_LOG);
-               aoview_log_save_conf();
-       } else {
-               aoview_log_dir = strdup(log_dir);
-       }
+       aoview_log = aoview_file_new("log");
+       assert(aoview_log);
 
-       log_chooser_dialog = GTK_FILE_CHOOSER(glade_xml_get_widget(xml, "log_chooser_dialog"));
-       assert(log_chooser_dialog);
-       gtk_file_chooser_set_filename(log_chooser_dialog, aoview_log_dir);
-
-       log_configure_ok = glade_xml_get_widget(xml, "log_configure_ok");
-       assert(log_configure_ok);
-
-       g_signal_connect(G_OBJECT(log_configure_ok), "clicked",
-                        G_CALLBACK(aoview_log_configure),
-                        log_chooser_dialog);
-
-       log_new = glade_xml_get_widget(xml, "ao_log_new");
+       log_new = glade_xml_get_widget(xml, "log_new");
        assert(log_new);
        g_signal_connect(G_OBJECT(log_new), "activate",
                         G_CALLBACK(aoview_log_new_item),
                         NULL);
-
-       log_fail_dialog = GTK_MESSAGE_DIALOG(glade_xml_get_widget(xml, "log_fail_dialog"));
-       assert(log_fail_dialog);
 }
index a3dc95441ed2a9c261d26e49f8e202dc2cb0724f..8d000993338ec269af2540802e42515c5ff41b97 100644 (file)
@@ -81,6 +81,8 @@ int main(int argc, char **argv)
 
        aoview_state_init(xml);
 
+       aoview_file_init(xml);
+
        aoview_log_init(xml);
 
        aoview_table_init(xml);