Diff of /trunk/src/geotoad.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 194 by harbaum, Wed Nov 18 11:40:31 2009 UTC revision 200 by harbaum, Thu Nov 19 13:57:17 2009 UTC
# Line 23  Line 23 
23  #include <sys/types.h>  #include <sys/types.h>
24  #include <sys/wait.h>  #include <sys/wait.h>
25  #include <errno.h>  #include <errno.h>
26    #include <math.h>
27    
28  #define COLOR_ERR  "red"  #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR >= 5)
29  #define COLOR_OK   "darkgreen"  #include <hildon/hildon-entry.h>
30    #endif
31    
32    #define GEOTOAD "/usr/bin/geotoad"
33    
34    #define COLOR_ERR     "red"
35    #define COLOR_OK      "darkgreen"
36    #define COLOR_SYSTEM  "darkblue"
37    
38  #define BUFFER_SIZE  1500  #define BUFFER_SIZE  256
39    
40  typedef struct {  typedef struct {
41    appdata_t *appdata;    appdata_t *appdata;
42    
43      GtkWidget *dialog;
44    
45    char buf[BUFFER_SIZE];    char buf[BUFFER_SIZE];
46    int bused;    int bused;
47    
# Line 43  typedef struct { Line 53  typedef struct {
53      GtkTextBuffer *buffer;      GtkTextBuffer *buffer;
54      GtkWidget *view;      GtkWidget *view;
55    } log;    } log;
56    
57      GtkWidget *username, *password, *filename;
58      GtkWidget *lat, *lon, *dst;
59    
60  } gt_context_t;  } gt_context_t;
61    
# Line 53  static void appendf(struct log_s *log, c Line 66  static void appendf(struct log_s *log, c
66    char *buf = g_strdup_vprintf(fmt, args);    char *buf = g_strdup_vprintf(fmt, args);
67    va_end( args );    va_end( args );
68    
69      printf("append: %s", buf);
70    
71    GtkTextTag *tag = NULL;    GtkTextTag *tag = NULL;
72    if(colname)    if(colname)
73      tag = gtk_text_buffer_create_tag(log->buffer, NULL,      tag = gtk_text_buffer_create_tag(log->buffer, NULL,
# Line 68  static void appendf(struct log_s *log, c Line 83  static void appendf(struct log_s *log, c
83    
84    g_free(buf);    g_free(buf);
85    
86      gtk_text_buffer_get_end_iter(log->buffer, &end);
87    gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(log->view),    gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(log->view),
88                                 &end, 0.0, FALSE, 0, 0);                                 &end, 0.0, FALSE, 0, 0);
89  }  }
90    
91  /* watch child process and receive events */  /* watch child process and receive events */
92  static void child_state_cb(GPid pid, gint status, gpointer data) {  static void child_state_cb(GPid pid, gint status, gpointer data) {
93      gt_context_t *context = (gt_context_t*)data;
94    
95    puts("child state");    puts("child state");
96    
# Line 84  static void child_state_cb(GPid pid, gin Line 101  static void child_state_cb(GPid pid, gin
101    
102    puts("gt exited");    puts("gt exited");
103    
104      appendf(&context->log, COLOR_SYSTEM, "GeoToad finished\n");
105    
106      appendf(&context->log, COLOR_SYSTEM, "TODO: free context!!!\n");
107      //    printf("freeing context\n");
108      //    g_free(context);
109    
110    /* Reap child if needed. */    /* Reap child if needed. */
111    waitpid (pid, NULL, WNOHANG);    waitpid (pid, NULL, WNOHANG);
112  }  }
113    
114  static void child_input_cb(gpointer data, int fd, GdkInputCondition cond) {  static gboolean child_input_cb(GIOChannel *source,
115                                   GIOCondition condition,
116                                   gpointer data) {
117    gt_context_t *context = (gt_context_t*)data;    gt_context_t *context = (gt_context_t*)data;
118      int fd = g_io_channel_unix_get_fd(source);
119    ssize_t bytes;    ssize_t bytes;
   int errnosave=0;  
120    
121    if(cond != GDK_INPUT_READ) {    g_assert(condition == G_IO_IN);
     puts("fixme");  
     return;  
   }  
122    
123    /* append to current buffer content */    /* append to current buffer content */
124    while( (bytes = read(fd, context->buf+context->bused,    while( (bytes = read(fd, context->buf+context->bused,
# Line 113  static void child_input_cb(gpointer data Line 134  static void child_input_cb(gpointer data
134        char *p = strchr(ptr, '\n');        char *p = strchr(ptr, '\n');
135        *p = '\0';        *p = '\0';
136    
137        appendf(&context->log, NULL, "%s\n", ptr);        char *color = NULL;
138          if(strstr(ptr, "Saved to ") != NULL)
139            color = COLOR_OK;
140    
141          appendf(&context->log, color, "%s\n", ptr);
142    
143        ptr = p+1;        ptr = p+1;
144      }      }
# Line 129  static void child_input_cb(gpointer data Line 154  static void child_input_cb(gpointer data
154      }      }
155    }    }
156    
157    /* save errno from read */    return TRUE;
158    errnosave=errno;  }
   
   if(errnosave != EAGAIN && errnosave != 0) {  
     /* we probably hit EOF */  
     puts("removing io");  
   
     // TODO: fixme, make sure process is dead! kill it otherwise, but dont  
     // issue an disconnect(NULL) !!!!  
   
     gdk_input_remove(context->stdout_tag);  
     gdk_input_remove(context->stderr_tag);  
159    
160      appendf(&context->log, COLOR_OK, "GeoToad finished\n");  static void arg_free(gpointer data, gpointer user_data) {
161      if(data) g_free(data);
162    }
163    
164      appendf(&context->log, COLOR_ERR, "TODO: free context!!!\n");  static void arg_dsp(gpointer data, gpointer user_data) {
165      //    printf("freeing context\n");    gt_context_t *context = (gt_context_t*)user_data;
166      //    g_free(context);  
167    }    if(data)
168        appendf(&context->log, COLOR_SYSTEM, "%s\n", data);
169  }  }
170    
171  static void run(gt_context_t *context) {  static void run(gt_context_t *context) {
172      char str[8];
173    
174    /* setup context */    /* setup context */
175    context->bused = 0;    context->bused = 0;
176    context->stdout_tag = -1;    context->stdout_tag = -1;
# Line 161  static void run(gt_context_t *context) { Line 181  static void run(gt_context_t *context) {
181    
182    /* build list of arguments to call geotoad */    /* build list of arguments to call geotoad */
183    GPtrArray *gt_argv = g_ptr_array_new();    GPtrArray *gt_argv = g_ptr_array_new();
184    g_ptr_array_add (gt_argv, "/usr/bin/geotoad");    g_ptr_array_add (gt_argv, g_strdup_printf(GEOTOAD));
185    g_ptr_array_add (gt_argv, "--distanceMax=1.5");    g_ascii_dtostr(str, sizeof(str), context->appdata->gt.distance);
186    g_ptr_array_add (gt_argv, "--output=gtoad.gpx");    g_ptr_array_add (gt_argv, g_strdup_printf("--distanceMax=%s", str));
187    g_ptr_array_add (gt_argv, "--password=winterblume");    g_ptr_array_add (gt_argv, g_strdup_printf("--output=%s", context->appdata->gt.filename));
188    g_ptr_array_add (gt_argv, "--queryType=coord");    g_ptr_array_add (gt_argv, g_strdup_printf("--password=%s", context->appdata->gt.password));
189    g_ptr_array_add (gt_argv, "--user=Tantil");    g_ptr_array_add (gt_argv, g_strdup_printf("--queryType=coord"));
190      g_ptr_array_add (gt_argv, g_strdup_printf("--user=%s", context->appdata->gt.username));
191    
192    /* check if we need to add proxy config */    /* check if we need to add proxy config */
193    char *proxy = NULL;    char *proxy = NULL;
# Line 184  static void run(gt_context_t *context) { Line 205  static void run(gt_context_t *context) {
205                                context->appdata->proxy->host,                                context->appdata->proxy->host,
206                                context->appdata->proxy->port);                                context->appdata->proxy->port);
207    
     appendf(&context->log, COLOR_OK, "Using proxy: %s\n", proxy);  
208      g_ptr_array_add (gt_argv, proxy);      g_ptr_array_add (gt_argv, proxy);
209    }    }
210    
211      g_ptr_array_add (gt_argv, g_strdup_printf("N49 00.000 E008 23.000"));
   g_ptr_array_add (gt_argv, "N49 00.000 E008 23.000");  
212    g_ptr_array_add (gt_argv, NULL);    g_ptr_array_add (gt_argv, NULL);
213    
214      /* show all entries */
215      g_ptr_array_foreach(gt_argv, arg_dsp, context);
216    
217    GError *error=NULL;    GError *error=NULL;
218    GPid pid;    GPid pid;
219    GSource *gt_watch;    GSource *gt_watch;
# Line 207  static void run(gt_context_t *context) { Line 229  static void run(gt_context_t *context) {
229                                   &context->stdout_fd,                                   &context->stdout_fd,
230                                   &context->stderr_fd,                                   &context->stderr_fd,
231                                   &error)) {                                   &error)) {
232        g_ptr_array_foreach(gt_argv, arg_free, NULL);
233      g_ptr_array_free(gt_argv, TRUE);      g_ptr_array_free(gt_argv, TRUE);
     if(proxy) g_free(proxy);  
234      appendf(&context->log, COLOR_ERR,      appendf(&context->log, COLOR_ERR,
235              _("GeoToad failed to start: '%s'"), error->message);              _("GeoToad failed to start!\n%s\n"), error->message);
236      g_error_free(error);      g_error_free(error);
237      return;      return;
238    }    }
239    
240      g_ptr_array_foreach(gt_argv, arg_free, NULL);
241    g_ptr_array_free (gt_argv, TRUE);    g_ptr_array_free (gt_argv, TRUE);
     if(proxy) g_free(proxy);  
242    
243    gt_watch = g_child_watch_source_new(pid);    gt_watch = g_child_watch_source_new(pid);
244    g_source_set_callback(gt_watch, (GSourceFunc) child_state_cb, NULL, NULL);    g_source_set_callback(gt_watch, (GSourceFunc) child_state_cb, context, NULL);
245    
246    g_source_attach(gt_watch, NULL);    g_source_attach(gt_watch, NULL);
247    g_source_unref(gt_watch);    g_source_unref(gt_watch);
# Line 230  static void run(gt_context_t *context) { Line 253  static void run(gt_context_t *context) {
253    if(fcntl(context->stderr_fd, F_SETFL, O_NONBLOCK) == -1)    if(fcntl(context->stderr_fd, F_SETFL, O_NONBLOCK) == -1)
254      perror("fcntl failed");      perror("fcntl failed");
255    
256    /* use gdk to monitor read end of stdout */    GIOChannel *ioc = g_io_channel_unix_new(context->stdout_fd);
257    context->stdout_tag = gdk_input_add(context->stdout_fd,    g_io_channel_set_close_on_unref (ioc, TRUE);
258                    GDK_INPUT_READ, child_input_cb, context);    g_io_channel_set_encoding (ioc, NULL, NULL);
259    context->stderr_tag = gdk_input_add(context->stderr_fd,    g_io_add_watch(ioc, G_IO_IN,  child_input_cb, context);
260                    GDK_INPUT_READ, child_input_cb, context);    g_io_channel_unref(ioc);
261    
262      //  ioc = g_io_channel_unix_new(context->stderr_fd);
263      //  g_io_add_watch(ioc, G_IO_IN,  child_input_cb, context);
264      //  g_io_channel_unref(ioc);
265  }  }
266    
267  void geotoad(appdata_t *appdata) {  /* show text window and display output of running geotoad */
268    gt_context_t *context = g_new0(gt_context_t, 1);  static void gui_run(gt_context_t *context) {
269    context->appdata = appdata;    GtkWidget *dialog = gtk_dialog_new_with_buttons(_("GeoToad - Run"),
270                              GTK_WINDOW(context->appdata->window),
   printf("geoToad\n");  
   
   GtkWidget *dialog = gtk_dialog_new_with_buttons(_("GeoToad"),  
                           GTK_WINDOW(appdata->window),  
271                            GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,                            GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
272                            GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,                            GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
273                            NULL);                            NULL);
# Line 286  void geotoad(appdata_t *appdata) { Line 309  void geotoad(appdata_t *appdata) {
309    
310    gtk_widget_show_all(dialog);    gtk_widget_show_all(dialog);
311    
312    appendf(&context->log, COLOR_OK, "Running GeoToad\n");    appendf(&context->log, COLOR_SYSTEM, "Running GeoToad\n");
313    run(context);    run(context);
314    
315    gtk_dialog_run(GTK_DIALOG(dialog));    gtk_dialog_run(GTK_DIALOG(dialog));
316    
317    gtk_widget_destroy(dialog);    gtk_widget_destroy(dialog);
318  }  }
319    
320    static void on_browse(GtkWidget *widget, gpointer data) {
321      gt_context_t *context = (gt_context_t*)data;
322    
323      printf("Browse %p\n", context->dialog);
324    
325    #ifdef USE_MAEMO
326      GtkWidget *dialog = hildon_file_chooser_dialog_new(GTK_WINDOW(context->dialog),
327                                              GTK_FILE_CHOOSER_ACTION_SAVE);
328    #else
329      GtkWidget *dialog = gtk_file_chooser_dialog_new(_("Save GPX file"),
330                                           GTK_WINDOW(context->dialog),
331                                           GTK_FILE_CHOOSER_ACTION_SAVE,
332                                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
333                                           GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
334                                           NULL);
335    #endif
336    
337      printf("set filename <%s>\n", context->appdata->gt.filename);
338    
339      if(!g_file_test(context->appdata->gt.filename, G_FILE_TEST_EXISTS)) {
340        char *last_sep = strrchr(context->appdata->gt.filename, '/');
341        if(last_sep) {
342          *last_sep = 0;  // seperate path from file
343    
344          /* the user just created a new document */
345          gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog),
346                                              context->appdata->gt.filename);
347          gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), last_sep+1);
348    
349          /* restore full filename */
350          *last_sep = '/';
351        }
352      } else
353        gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog),
354                                      context->appdata->gt.filename);
355    
356      if (gtk_dialog_run (GTK_DIALOG(dialog)) == GTK_FM_OK) {
357        gchar *name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
358        gtk_label_set_text(GTK_LABEL(context->filename), name);
359      }
360    
361      gtk_widget_destroy (dialog);
362    }
363    
364    static gboolean gui_setup(gt_context_t *context) {
365      appdata_t *appdata = context->appdata;
366      gboolean ok = FALSE;
367    
368      /* if no filename has been setup yet, create one */
369      if(!appdata->gt.filename && appdata->path) {
370        printf("creating path\n");
371        appdata->gt.filename =
372          g_strdup_printf("%s/gtoad.gpx", appdata->path);
373      }
374    
375      context->dialog = gtk_dialog_new_with_buttons(_("GeoToad - Setup"),
376                            GTK_WINDOW(appdata->window),
377                            GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
378                            GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
379                            GTK_STOCK_OK,     GTK_RESPONSE_OK,
380                            NULL);
381    
382      /* ------------------- Coordinates ------------------------- */
383      GtkWidget *hbox = gtk_hbox_new(FALSE, 0);
384    
385      GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
386      gtk_box_pack_start_defaults(GTK_BOX(vbox), left_label_new(_("Position:")));
387      gtk_box_pack_start_defaults(GTK_BOX(vbox), left_label_new(_("Distance:")));
388      gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
389    
390      /* setup default positions */
391      pos_t *refpos = get_pos(appdata);
392      if((isnan(appdata->gt.lat) || isnan(appdata->gt.lat)) && refpos) {
393        appdata->gt.lat = refpos->lat;
394        appdata->gt.lon = refpos->lon;
395      }
396    
397      vbox = gtk_vbox_new(FALSE, 0);
398      GtkWidget *ihbox = gtk_hbox_new(FALSE, 0);
399      context->lat = lat_entry_new(appdata->gt.lat);
400      gtk_box_pack_start_defaults(GTK_BOX(ihbox), context->lat);
401      context->lon = lon_entry_new(appdata->gt.lon);
402      gtk_box_pack_start_defaults(GTK_BOX(ihbox), context->lon);
403      gtk_box_pack_start_defaults(GTK_BOX(vbox), ihbox);
404      float dst = appdata->gt.distance;  // distance is given in kilometers
405      if(appdata->imperial) dst /= 1.609344;
406      context->dst = dist_entry_new(dst, appdata->imperial);
407      gtk_box_pack_start_defaults(GTK_BOX(vbox), context->dst);
408      gtk_box_pack_start_defaults(GTK_BOX(hbox), vbox);
409    
410      gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(context->dialog)->vbox), hbox);
411    
412      /* ------------------- file name ------------------------- */
413      hbox = gtk_hbox_new(FALSE, 0);
414    
415      context->filename = gtk_label_new(appdata->gt.filename);
416      gtk_misc_set_alignment(GTK_MISC(context->filename), 0.f, 0.5f);
417      gtk_label_set_ellipsize(GTK_LABEL(context->filename), PANGO_ELLIPSIZE_MIDDLE);
418      gtk_box_pack_start_defaults(GTK_BOX(hbox), context->filename);
419    
420      GtkWidget *button = gtk_button_new_with_label(_("Browse"));
421    #if defined(USE_MAEMO) && (MAEMO_VERSION_MAJOR == 5)
422      hildon_gtk_widget_set_theme_size(button,
423               (HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH));
424    #endif
425      gtk_signal_connect(GTK_OBJECT(button), "clicked",
426                         GTK_SIGNAL_FUNC(on_browse), context);
427      gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
428    
429      gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(context->dialog)->vbox), hbox);
430    
431    
432      /* ------------------- Username/Password ------------------------- */
433      hbox = gtk_hbox_new(FALSE, 0);
434      vbox = gtk_vbox_new(FALSE, 0);
435      gtk_box_pack_start_defaults(GTK_BOX(vbox), left_label_new(_("Username:")));
436      gtk_box_pack_start_defaults(GTK_BOX(vbox), left_label_new(_("Password:")));
437      gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
438    
439      vbox = gtk_vbox_new(FALSE, 0);
440    #if !defined(USE_MAEMO) || (MAEMO_VERSION_MAJOR < 5)
441      context->username = gtk_entry_new();
442      context->password = gtk_entry_new();
443    #else
444      context->username = hildon_entry_new(HILDON_SIZE_AUTO);
445      hildon_gtk_entry_set_input_mode(GTK_ENTRY(context->username),
446                                      HILDON_GTK_INPUT_MODE_FULL);
447      context->password = hildon_entry_new(HILDON_SIZE_AUTO);
448      hildon_gtk_entry_set_input_mode(GTK_ENTRY(context->password),
449                                      HILDON_GTK_INPUT_MODE_FULL);
450    #endif
451      gtk_entry_set_visibility(GTK_ENTRY(context->password), FALSE);
452    
453      /* set saved defaults */
454      if(appdata->gt.username)
455        gtk_entry_set_text(GTK_ENTRY(context->username),
456                           appdata->gt.username);
457    
458      if(appdata->gt.password)
459        gtk_entry_set_text(GTK_ENTRY(context->password),
460                           appdata->gt.password);
461    
462      gtk_box_pack_start_defaults(GTK_BOX(vbox), context->username);
463      gtk_box_pack_start_defaults(GTK_BOX(vbox), context->password);
464      gtk_box_pack_start_defaults(GTK_BOX(hbox), vbox);
465    
466      gtk_box_pack_start_defaults(GTK_BOX(GTK_DIALOG(context->dialog)->vbox), hbox);
467    
468      gtk_dialog_set_default_response(GTK_DIALOG(context->dialog), GTK_RESPONSE_OK);
469    
470      gtk_widget_show_all(context->dialog);
471    
472      if(gtk_dialog_run(GTK_DIALOG(context->dialog)) == GTK_RESPONSE_OK) {
473    
474        /* parse coordinates */
475        /* ... */
476    
477        /* save values */
478        if(appdata->gt.username) g_free(appdata->gt.username);
479        appdata->gt.username =
480          g_strdup(gtk_entry_get_text(GTK_ENTRY(context->username)));
481    
482        if(appdata->gt.password) g_free(appdata->gt.password);
483        appdata->gt.password =
484          g_strdup(gtk_entry_get_text(GTK_ENTRY(context->password)));
485    
486        if(appdata->gt.filename) g_free(appdata->gt.filename);
487        appdata->gt.filename =
488          g_strdup(gtk_label_get_text(GTK_LABEL(context->filename)));
489    
490        /* get distance in kilometers */
491        appdata->gt.distance = dist_get(context->dst, FALSE);
492    
493        ok = TRUE;
494      }
495    
496      gtk_widget_destroy(context->dialog);
497    
498      return ok;
499    }
500    
501    void geotoad(appdata_t *appdata) {
502      if(!geotoad_available()) {
503        errorf(_("GeoToad is not installed on this device.\n"
504                 "You need to install it in order to be able to use it."));
505        return;
506      }
507    
508      gt_context_t *context = g_new0(gt_context_t, 1);
509      context->appdata = appdata;
510    
511      printf("geoToad\n");
512    
513      if(gui_setup(context))
514        gui_run(context);
515    }
516    
517    gboolean geotoad_available(void) {
518      /* before doing anything make sure geotoad is installed */
519      return g_file_test(GEOTOAD, G_FILE_TEST_IS_EXECUTABLE);
520    }
521    
522    

Legend:
Removed from v.194  
changed lines
  Added in v.200