Contents of /trunk/src/geotoad.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 194 - (hide annotations)
Wed Nov 18 11:40:31 2009 UTC (14 years, 6 months ago) by harbaum
File MIME type: text/plain
File size: 8530 byte(s)
Some geotoad work
1 harbaum 193 /*
2     * Copyright (C) 2009 Till Harbaum <till@harbaum.org>.
3     *
4     * This file is part of GPXView.
5     *
6     * GPXView is free software: you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation, either version 3 of the License, or
9     * (at your option) any later version.
10     *
11     * GPXView is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with GPXView. If not, see <http://www.gnu.org/licenses/>.
18     */
19    
20     #include "gpxview.h"
21    
22     #include <fcntl.h>
23     #include <sys/types.h>
24     #include <sys/wait.h>
25     #include <errno.h>
26    
27 harbaum 194 #define COLOR_ERR "red"
28     #define COLOR_OK "darkgreen"
29    
30 harbaum 193 #define BUFFER_SIZE 1500
31    
32     typedef struct {
33 harbaum 194 appdata_t *appdata;
34    
35 harbaum 193 char buf[BUFFER_SIZE];
36     int bused;
37    
38     /** gdk input tag for async IO */
39     gint stdout_tag, stderr_tag;
40     gint stdin_fd, stdout_fd, stderr_fd;
41    
42 harbaum 194 struct log_s {
43     GtkTextBuffer *buffer;
44     GtkWidget *view;
45     } log;
46    
47 harbaum 193 } gt_context_t;
48    
49 harbaum 194 static void appendf(struct log_s *log, char *colname,
50     const char *fmt, ...) {
51     va_list args;
52     va_start( args, fmt );
53     char *buf = g_strdup_vprintf(fmt, args);
54     va_end( args );
55    
56     GtkTextTag *tag = NULL;
57     if(colname)
58     tag = gtk_text_buffer_create_tag(log->buffer, NULL,
59     "foreground", colname,
60     NULL);
61    
62     GtkTextIter end;
63     gtk_text_buffer_get_end_iter(log->buffer, &end);
64     if(tag)
65     gtk_text_buffer_insert_with_tags(log->buffer, &end, buf, -1, tag, NULL);
66     else
67     gtk_text_buffer_insert(log->buffer, &end, buf, -1);
68    
69     g_free(buf);
70    
71     gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(log->view),
72     &end, 0.0, FALSE, 0, 0);
73     }
74    
75 harbaum 193 /* watch child process and receive events */
76     static void child_state_cb(GPid pid, gint status, gpointer data) {
77    
78     puts("child state");
79    
80     if(WIFEXITED(status)) {
81 harbaum 194 printf("child exited with return code %d\n", WEXITSTATUS(status));
82     } else
83     printf("child failed\n");
84 harbaum 193
85     puts("gt exited");
86    
87     /* Reap child if needed. */
88     waitpid (pid, NULL, WNOHANG);
89     }
90    
91     static void child_input_cb(gpointer data, int fd, GdkInputCondition cond) {
92     gt_context_t *context = (gt_context_t*)data;
93    
94     ssize_t bytes;
95     int errnosave=0;
96    
97     if(cond != GDK_INPUT_READ) {
98     puts("fixme");
99     return;
100     }
101    
102     /* append to current buffer content */
103     while( (bytes = read(fd, context->buf+context->bused,
104     sizeof(context->buf) - context->bused - 1)) > 0) {
105     context->bused += bytes;
106     context->buf[context->bused]='\0';
107    
108     /* consume line by line */
109     gchar *ptr = context->buf;
110    
111     /* parse as long as the buffer contains a newline */
112     while( strchr(ptr, '\n') != NULL) {
113     char *p = strchr(ptr, '\n');
114     *p = '\0';
115    
116 harbaum 194 appendf(&context->log, NULL, "%s\n", ptr);
117 harbaum 193
118     ptr = p+1;
119     }
120    
121     /* move remaining bytes down the buffer */
122     memmove(context->buf, ptr, sizeof(context->buf)-(ptr-context->buf));
123     context->bused -= ptr - context->buf;
124    
125     /* check if buffer is full but doesn't contain any newline */
126     if(context->bused >= sizeof(context->buf)-1) {
127     printf("ERROR: reply buffer overflow\n");
128     context->bused = 0;
129     }
130     }
131    
132     /* save errno from read */
133     errnosave=errno;
134    
135     if(errnosave != EAGAIN && errnosave != 0) {
136     /* we probably hit EOF */
137     puts("removing io");
138    
139     // TODO: fixme, make sure process is dead! kill it otherwise, but dont
140 harbaum 194 // issue an disconnect(NULL) !!!!
141 harbaum 193
142     gdk_input_remove(context->stdout_tag);
143     gdk_input_remove(context->stderr_tag);
144    
145 harbaum 194 appendf(&context->log, COLOR_OK, "GeoToad finished\n");
146    
147     appendf(&context->log, COLOR_ERR, "TODO: free context!!!\n");
148     // printf("freeing context\n");
149     // g_free(context);
150 harbaum 193 }
151     }
152    
153 harbaum 194 static void run(gt_context_t *context) {
154 harbaum 193 /* setup context */
155     context->bused = 0;
156     context->stdout_tag = -1;
157     context->stderr_tag = -1;
158     context->stdin_fd = -1;
159     context->stderr_fd = -1;
160     context->stderr_fd = -1;
161    
162 harbaum 194 /* build list of arguments to call geotoad */
163 harbaum 193 GPtrArray *gt_argv = g_ptr_array_new();
164 harbaum 194 g_ptr_array_add (gt_argv, "/usr/bin/geotoad");
165     g_ptr_array_add (gt_argv, "--distanceMax=1.5");
166     g_ptr_array_add (gt_argv, "--output=gtoad.gpx");
167     g_ptr_array_add (gt_argv, "--password=winterblume");
168     g_ptr_array_add (gt_argv, "--queryType=coord");
169     g_ptr_array_add (gt_argv, "--user=Tantil");
170    
171     /* check if we need to add proxy config */
172     char *proxy = NULL;
173     if(context->appdata->proxy && context->appdata->proxy->host) {
174     if(context->appdata->proxy->use_authentication &&
175     context->appdata->proxy->authentication_user &&
176     context->appdata->proxy->authentication_password)
177     proxy = g_strdup_printf("--proxy=http://%s:%s@%s:%d",
178     context->appdata->proxy->authentication_user,
179     context->appdata->proxy->authentication_password,
180     context->appdata->proxy->host,
181     context->appdata->proxy->port);
182     else
183     proxy = g_strdup_printf("--proxy=http://%s:%d",
184     context->appdata->proxy->host,
185     context->appdata->proxy->port);
186    
187     appendf(&context->log, COLOR_OK, "Using proxy: %s\n", proxy);
188     g_ptr_array_add (gt_argv, proxy);
189     }
190    
191    
192     g_ptr_array_add (gt_argv, "N49 00.000 E008 23.000");
193 harbaum 193 g_ptr_array_add (gt_argv, NULL);
194 harbaum 194
195 harbaum 193 GError *error=NULL;
196     GPid pid;
197     GSource *gt_watch;
198    
199     if (!g_spawn_async_with_pipes (NULL, /* CWD */
200     (char **) gt_argv->pdata, /* argv */
201     NULL, /* envp */
202     G_SPAWN_DO_NOT_REAP_CHILD, /* flags */
203     NULL, /* child setup */
204     NULL, /* user data */
205     &pid,
206     &context->stdin_fd,
207     &context->stdout_fd,
208     &context->stderr_fd,
209     &error)) {
210     g_ptr_array_free(gt_argv, TRUE);
211 harbaum 194 if(proxy) g_free(proxy);
212     appendf(&context->log, COLOR_ERR,
213     _("GeoToad failed to start: '%s'"), error->message);
214 harbaum 193 g_error_free(error);
215     return;
216     }
217     g_ptr_array_free (gt_argv, TRUE);
218 harbaum 194 if(proxy) g_free(proxy);
219 harbaum 193
220     gt_watch = g_child_watch_source_new(pid);
221     g_source_set_callback(gt_watch, (GSourceFunc) child_state_cb, NULL, NULL);
222    
223     g_source_attach(gt_watch, NULL);
224     g_source_unref(gt_watch);
225    
226     /* make nonblocking */
227     if(fcntl(context->stdout_fd, F_SETFL, O_NONBLOCK) == -1)
228     perror("fcntl failed");
229    
230     if(fcntl(context->stderr_fd, F_SETFL, O_NONBLOCK) == -1)
231     perror("fcntl failed");
232    
233     /* use gdk to monitor read end of stdout */
234 harbaum 194 context->stdout_tag = gdk_input_add(context->stdout_fd,
235     GDK_INPUT_READ, child_input_cb, context);
236     context->stderr_tag = gdk_input_add(context->stderr_fd,
237     GDK_INPUT_READ, child_input_cb, context);
238 harbaum 193 }
239 harbaum 194
240     void geotoad(appdata_t *appdata) {
241     gt_context_t *context = g_new0(gt_context_t, 1);
242     context->appdata = appdata;
243    
244     printf("geoToad\n");
245    
246     GtkWidget *dialog = gtk_dialog_new_with_buttons(_("GeoToad"),
247     GTK_WINDOW(appdata->window),
248     GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
249     GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
250     NULL);
251    
252     gtk_window_set_default_size(GTK_WINDOW(dialog), 640, 480);
253    
254     #ifndef USE_PANNABLE_AREA
255     GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL);
256     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window),
257     GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
258     #else
259     GtkWidget *pannable_area = hildon_pannable_area_new();
260     #endif
261    
262     context->log.buffer = gtk_text_buffer_new(NULL);
263    
264     #ifndef USE_HILDON_TEXT_VIEW
265     context->log.view = gtk_text_view_new_with_buffer(context->log.buffer);
266     #else
267     context->log.view = hildon_text_view_new();
268     hildon_text_view_set_buffer(HILDON_TEXT_VIEW(context->log.view),
269     context->log.buffer);
270     #endif
271    
272     #ifndef USE_PANNABLE_AREA
273     gtk_container_add(GTK_CONTAINER(scrolled_window), context->log.view);
274     gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW(scrolled_window),
275     GTK_SHADOW_IN);
276    
277     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
278     scrolled_window, TRUE, TRUE, 0);
279     #else
280     gtk_container_add(GTK_CONTAINER(pannable_area), context->log.view);
281     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
282     pannable_area, TRUE, TRUE, 0);
283     #endif
284    
285     gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE);
286    
287     gtk_widget_show_all(dialog);
288    
289     appendf(&context->log, COLOR_OK, "Running GeoToad\n");
290     run(context);
291    
292     gtk_dialog_run(GTK_DIALOG(dialog));
293    
294     gtk_widget_destroy(dialog);
295     }