+
+static void set_mode(BabelMode *mode, gchar *smode)
+{
+ mode->waypointsRead = smode[0] == 'r';
+ mode->waypointsWrite = smode[1] == 'w';
+ mode->tracksRead = smode[2] == 'r';
+ mode->tracksWrite = smode[3] == 'w';
+ mode->routesRead = smode[4] == 'r';
+ mode->routesWrite = smode[5] == 'w';
+}
+
+/**
+ * load_feature_parse_line:
+ *
+ * Load a single feature stored in the given line.
+ */
+static void load_feature_parse_line (gchar *line)
+{
+ gchar **tokens = g_strsplit ( line, "\t", 0 );
+ if ( tokens != NULL
+ && tokens[0] != NULL ) {
+ if ( strcmp("serial", tokens[0]) == 0 ) {
+ if ( tokens[1] != NULL
+ && tokens[2] != NULL
+ && tokens[3] != NULL
+ && tokens[4] != NULL ) {
+ BabelDevice *device = g_malloc ( sizeof (BabelDevice) );
+ set_mode (&(device->mode), tokens[1]);
+ device->name = g_strdup (tokens[2]);
+ device->label = g_strndup (tokens[4], 50); // Limit really long label text
+ a_babel_device_list = g_list_append (a_babel_device_list, device);
+ g_debug ("New gpsbabel device: %s, %d%d%d%d%d%d(%s)",
+ device->name,
+ device->mode.waypointsRead, device->mode.waypointsWrite,
+ device->mode.tracksRead, device->mode.tracksWrite,
+ device->mode.routesRead, device->mode.routesWrite,
+ tokens[1]);
+ } else {
+ g_warning ( "Unexpected gpsbabel format string: %s", line);
+ }
+ } else if ( strcmp("file", tokens[0]) == 0 ) {
+ if ( tokens[1] != NULL
+ && tokens[2] != NULL
+ && tokens[3] != NULL
+ && tokens[4] != NULL ) {
+ BabelFile *file = g_malloc ( sizeof (BabelFile) );
+ set_mode (&(file->mode), tokens[1]);
+ file->name = g_strdup (tokens[2]);
+ file->ext = g_strdup (tokens[3]);
+ file->label = g_strdup (tokens[4]);
+ a_babel_file_list = g_list_append (a_babel_file_list, file);
+ g_debug ("New gpsbabel file: %s, %d%d%d%d%d%d(%s)",
+ file->name,
+ file->mode.waypointsRead, file->mode.waypointsWrite,
+ file->mode.tracksRead, file->mode.tracksWrite,
+ file->mode.routesRead, file->mode.routesWrite,
+ tokens[1]);
+ } else {
+ g_warning ( "Unexpected gpsbabel format string: %s", line);
+ }
+ } /* else: ignore */
+ } else {
+ g_warning ( "Unexpected gpsbabel format string: %s", line);
+ }
+ g_strfreev ( tokens );
+}
+
+static void load_feature_cb (BabelProgressCode code, gpointer line, gpointer user_data)
+{
+ if (line != NULL)
+ load_feature_parse_line (line);
+}
+
+static gboolean load_feature ()
+{
+ int i;
+ gboolean ret = FALSE;
+ gchar *args[4];
+
+ if ( gpsbabel_loc ) {
+ i = 0;
+ if ( unbuffer_loc )
+ args[i++] = unbuffer_loc;
+ args[i++] = gpsbabel_loc;
+ args[i++] = "-^3";
+ args[i] = NULL;
+
+ ret = babel_general_convert (load_feature_cb, args, NULL);
+ } else
+ g_critical("gpsbabel not found in PATH");
+
+ return ret;
+}
+
+static VikLayerParam prefs[] = {
+ { VIK_LAYER_NUM_TYPES, VIKING_PREFERENCES_IO_NAMESPACE "gpsbabel", VIK_LAYER_PARAM_STRING, VIK_LAYER_GROUP_NONE, N_("GPSBabel:"), VIK_LAYER_WIDGET_FILEENTRY, NULL, NULL,
+ N_("Allow setting the specific instance of GPSBabel. You must restart Viking for this value to take effect."), NULL, NULL, NULL },
+};
+
+/**
+ * a_babel_init:
+ *
+ * Just setup preferences first
+ */
+void a_babel_init ()
+{
+ // Set the defaults
+ VikLayerParamData vlpd;
+#ifdef WINDOWS
+ // Basic guesses - could use %ProgramFiles% but this is simpler:
+ if ( g_file_test ( "C:\\Program Files (x86)\\GPSBabel\\gpsbabel.exe", G_FILE_TEST_EXISTS ) )
+ // 32 bit location on a 64 bit system
+ vlpd.s = "C:\\Program Files (x86)\\GPSBabel\\gpsbabel.exe";
+ else
+ vlpd.s = "C:\\Program Files\\GPSBabel\\gpsbabel.exe";
+#else
+ vlpd.s = "gpsbabel";
+#endif
+ a_preferences_register(&prefs[0], vlpd, VIKING_PREFERENCES_IO_GROUP_KEY);
+}
+
+/**
+ * a_babel_post_init:
+ *
+ * Initialises babel module.
+ * Mainly check existence of gpsbabel progam
+ * and load all features available in that version.
+ */
+void a_babel_post_init ()
+{
+ // Read the current preference
+ const gchar *gpsbabel = a_preferences_get(VIKING_PREFERENCES_IO_NAMESPACE "gpsbabel")->s;
+ // If setting is still the UNIX default then lookup in the path - otherwise attempt to use the specified value directly.
+ if ( g_strcmp0 ( gpsbabel, "gpsbabel" ) == 0 ) {
+ gpsbabel_loc = g_find_program_in_path( "gpsbabel" );
+ if ( !gpsbabel_loc )
+ g_critical( "gpsbabel not found in PATH" );
+ }
+ else
+ gpsbabel_loc = (gchar*)gpsbabel;
+
+ // Unlikely to package unbuffer on Windows so ATM don't even bother trying
+ // Highly unlikely unbuffer is available on a Windows system otherwise
+#ifndef WINDOWS
+ unbuffer_loc = g_find_program_in_path( "unbuffer" );
+ if ( !unbuffer_loc )
+ g_warning( "unbuffer not found in PATH" );
+#endif
+
+ load_feature ();
+}
+
+/**
+ * a_babel_uninit:
+ *
+ * Free resources acquired by a_babel_init.
+ */
+void a_babel_uninit ()
+{
+ g_free ( gpsbabel_loc );
+ g_free ( unbuffer_loc );
+
+ if ( a_babel_file_list ) {
+ GList *gl;
+ for (gl = a_babel_file_list; gl != NULL; gl = g_list_next(gl)) {
+ BabelFile *file = gl->data;
+ g_free ( file->name );
+ g_free ( file->ext );
+ g_free ( file->label );
+ g_free ( gl->data );
+ }
+ g_list_free ( a_babel_file_list );
+ }
+
+ if ( a_babel_device_list ) {
+ GList *gl;
+ for (gl = a_babel_device_list; gl != NULL; gl = g_list_next(gl)) {
+ BabelDevice *device = gl->data;
+ g_free ( device->name );
+ g_free ( device->label );
+ g_free ( gl->data );
+ }
+ g_list_free ( a_babel_device_list );
+ }
+
+}
+
+/**
+ * a_babel_available:
+ *
+ * Indicates if babel is available or not.
+ *
+ * Returns: true if babel available
+ */
+gboolean a_babel_available ()
+{
+ return a_babel_device_list != NULL;
+}