]> git.street.me.uk Git - andy/viking.git/blob - src/geojson.c
SF Bugs#132: Fix to correctly open GPX files in Windows via double click.
[andy/viking.git] / src / geojson.c
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3  * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
4  *
5  * Copyright (c) 2014, Rob Norris <rw_norris@hotmail.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  * See http://geojson.org/ for the specification
22  *
23  */
24
25 #include "geojson.h"
26 #include "gpx.h"
27 #include "globals.h"
28 #include "vikwindow.h"
29
30 #include <glib.h>
31 #include <glib/gstdio.h>
32 #include <glib/gi18n.h>
33
34 /**
35  * Perform any cleanup actions once program has completed running
36  */
37 static void my_watch ( GPid pid,
38                        gint status,
39                        gpointer user_data )
40 {
41         g_spawn_close_pid ( pid );
42 }
43
44 /**
45  * a_geojson_write_file:
46  *
47  * Returns TRUE if successfully written
48  */
49 gboolean a_geojson_write_file ( VikTrwLayer *vtl, FILE *ff )
50 {
51         gboolean result = FALSE;
52
53         gchar *tmp_filename = a_gpx_write_tmp_file ( vtl, NULL );
54         if ( !tmp_filename )
55                 return result;
56
57         GPid pid;
58         gint mystdout;
59
60         // geojson program should be on the $PATH
61         gchar **argv;
62         argv = g_new (gchar*, 5);
63         argv[0] = g_strdup (a_geojson_program_export());
64         argv[1] = g_strdup ("-f");
65         argv[2] = g_strdup ("gpx");
66         argv[3] = g_strdup (tmp_filename);
67         argv[4] = NULL;
68
69         GError *error = NULL;
70         // TODO: monitor stderr?
71         if (!g_spawn_async_with_pipes (NULL, argv, NULL, (GSpawnFlags) G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, NULL, &mystdout, NULL, &error)) {
72
73                 if ( IS_VIK_WINDOW ((VikWindow *)VIK_GTK_WINDOW_FROM_LAYER(vtl)) ) {
74                         gchar* msg = g_strdup_printf ( _("%s command failed: %s"), argv[0], error->message );
75                         vik_window_statusbar_update ( (VikWindow*)VIK_GTK_WINDOW_FROM_LAYER(vtl), msg, VIK_STATUSBAR_INFO );
76                         g_free (msg);
77                 }
78                 else
79                         g_warning ("Async command failed: %s", error->message);
80
81                 g_error_free(error);
82         }
83         else {
84                 // Probably should use GIOChannels...
85                 gchar line[512];
86                 FILE *fout = fdopen(mystdout, "r");
87                 setvbuf(fout, NULL, _IONBF, 0);
88
89                 while (fgets(line, sizeof(line), fout)) {
90                         fprintf ( ff, "%s", line );
91                 }
92
93                 fclose(fout);
94
95                 g_child_watch_add ( pid, (GChildWatchFunc) my_watch, NULL );
96                 result = TRUE;
97         }
98
99         g_strfreev (argv);
100
101         // Delete the temporary file
102         (void)g_remove (tmp_filename);
103         g_free (tmp_filename);
104
105         return result;
106 }
107
108 //
109 // https://github.com/mapbox/togeojson
110 //
111 // https://www.npmjs.org/package/togeojson
112 //
113 // Tested with version 0.7.0
114 const gchar* a_geojson_program_export ( void )
115 {
116         return "togeojson";
117 }
118
119 //
120 // https://github.com/tyrasd/togpx
121 //
122 // https://www.npmjs.org/package/togpx
123 //
124 // Tested with version 0.3.1
125 const gchar* a_geojson_program_import ( void )
126 {
127         return "togpx";
128 }
129
130 /**
131  * a_geojson_import_to_gpx:
132  *
133  * @filename: The source GeoJSON file
134  *
135  * Returns: The name of newly created temporary GPX file
136  *          This file should be removed once used and the string freed.
137  *          If NULL then the process failed.
138  */
139 gchar* a_geojson_import_to_gpx ( const gchar *filename )
140 {
141         gchar *gpx_filename = NULL;
142         GError *error = NULL;
143         // Opening temporary file
144         int fd = g_file_open_tmp("vik_geojson_XXXXXX.gpx", &gpx_filename, &error);
145         if (fd < 0) {
146                 g_warning ( _("failed to open temporary file: %s"), error->message );
147                 g_clear_error ( &error );
148                 return NULL;
149         }
150         g_debug ( "%s: temporary file = %s", __FUNCTION__, gpx_filename );
151
152         GPid pid;
153         gint mystdout;
154
155         // geojson program should be on the $PATH
156         gchar **argv;
157         argv = g_new (gchar*, 3);
158         argv[0] = g_strdup (a_geojson_program_import());
159         argv[1] = g_strdup (filename);
160         argv[2] = NULL;
161
162         FILE *gpxfile = fdopen (fd, "w");
163
164         // TODO: monitor stderr?
165         if (!g_spawn_async_with_pipes (NULL, argv, NULL, (GSpawnFlags) G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, &pid, NULL, &mystdout, NULL, &error)) {
166                 g_warning ("Async command failed: %s", error->message);
167                 g_error_free(error);
168         }
169         else {
170                 // Probably should use GIOChannels...
171                 gchar line[512];
172                 FILE *fout = fdopen(mystdout, "r");
173                 setvbuf(fout, NULL, _IONBF, 0);
174
175                 while (fgets(line, sizeof(line), fout)) {
176                         fprintf ( gpxfile, "%s", line );
177                 }
178
179                 fclose(fout);
180                 g_child_watch_add ( pid, (GChildWatchFunc) my_watch, NULL );
181         }
182
183         fclose (gpxfile);
184
185         g_strfreev (argv);
186
187         return gpx_filename;
188 }