예제 #1
0
/**
 * a_geotag_write_exif_gps:
 * @filename: The image file to save information in
 * @coord:    The location
 * @alt:      The elevation
 *
 * Returns: A value indicating success: 0, or some other value for failure
 *
 */
gint a_geotag_write_exif_gps ( const gchar *filename, VikCoord coord, gdouble alt, gboolean no_change_mtime )
{
	gint result = 0; // OK so far...

	// Save mtime for later use
	struct stat stat_save;
	if ( no_change_mtime )
		stat ( filename, &stat_save );

	/*
	  Appears libexif doesn't actually support writing EXIF data directly to files
	  Thus embed command line exif writing method within Viking
	  (for example this is done by Enlightment - http://www.enlightenment.org/ )
	  This appears to be JPEG only, but is probably 99% of our use case
	  Alternatively consider using libexiv2 and C++...
	*/

	// Actual EXIF settings here...
	JPEGData *jdata;

	/* Parse the JPEG file. */
	jdata = jpeg_data_new ();
	jpeg_data_load_file (jdata, filename);

	// Get current values
	ExifData *ed = exif_data_new_from_file ( filename );
	if ( !ed )
		ed = exif_data_new ();

	// Update ExifData with our new settings
	ExifEntry *ee;
	//
	// I don't understand it, but when saving the 'ed' nothing gets set after putting in the GPS ID tag - so it must come last
	// (unless of course there is some bug in the setting of the ID, that prevents subsequent tags)
	//

	ee = my_exif_create_value (ed, EXIF_TAG_GPS_ALTITUDE, EXIF_IFD_GPS);
	convert_to_entry ( NULL, alt, ee, exif_data_get_byte_order(ed) );

	// byte 0 meaning "sea level" or 1 if the value is negative.
	ee = my_exif_create_value (ed, EXIF_TAG_GPS_ALTITUDE_REF, EXIF_IFD_GPS);
	convert_to_entry ( alt < 0.0 ? "1" : "0", 0.0, ee, exif_data_get_byte_order(ed) );

	ee = my_exif_create_value (ed, EXIF_TAG_GPS_PROCESSING_METHOD, EXIF_IFD_GPS);
	// see http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/GPS.html
	convert_to_entry ( "MANUAL", 0.0, ee, exif_data_get_byte_order(ed) );

	ee = my_exif_create_value (ed, EXIF_TAG_GPS_MAP_DATUM, EXIF_IFD_GPS);
	convert_to_entry ( "WGS-84", 0.0, ee, exif_data_get_byte_order(ed) );

	struct LatLon ll;
    vik_coord_to_latlon ( &coord, &ll );

	ee = my_exif_create_value (ed, EXIF_TAG_GPS_LATITUDE_REF, EXIF_IFD_GPS);
	// N or S
	convert_to_entry ( ll.lat < 0.0 ? "S" : "N", 0.0, ee, exif_data_get_byte_order(ed) );

	ee = my_exif_create_value (ed, EXIF_TAG_GPS_LATITUDE, EXIF_IFD_GPS);
	convert_to_entry ( NULL, ll.lat, ee, exif_data_get_byte_order(ed) );

	ee = my_exif_create_value (ed, EXIF_TAG_GPS_LONGITUDE_REF, EXIF_IFD_GPS);
	// E or W
	convert_to_entry ( ll.lon < 0.0 ? "W" : "E", 0.0, ee, exif_data_get_byte_order(ed) );

	ee = my_exif_create_value (ed, EXIF_TAG_GPS_LONGITUDE, EXIF_IFD_GPS);
	convert_to_entry ( NULL, ll.lon, ee, exif_data_get_byte_order(ed) );

	ee = my_exif_create_value (ed, EXIF_TAG_GPS_VERSION_ID, EXIF_IFD_GPS);
	//convert_to_entry ( "2 0 0 0", 0.0, ee, exif_data_get_byte_order(ed) );
	convert_to_entry ( "2 2 0 0", 0.0, ee, exif_data_get_byte_order(ed) );

	jpeg_data_set_exif_data (jdata, ed);

	if ( jdata ) {
		/* Save the modified image. */
		result = jpeg_data_save_file (jdata, filename);

		// Convert result from 1 for success, 0 for failure into our scheme
		result = !result;
		
		jpeg_data_unref (jdata);
	}
	else {
		// Epic fail - file probably not a JPEG
		result = 2;
	}

	if ( no_change_mtime ) {
		// Restore mtime, using the saved value
		struct stat stat_tmp;
		struct utimbuf utb;
		stat ( filename, &stat_tmp );
		utb.actime = stat_tmp.st_atime;
		utb.modtime = stat_save.st_mtime;
		utime ( filename, &utb );
	}

	return result;
}
예제 #2
0
/* todo: less on this side, like add track */
gchar *a_dialog_waypoint ( GtkWindow *parent, gchar *default_name, VikTrwLayer *vtl, VikWaypoint *wp, VikCoordMode coord_mode, gboolean is_new, gboolean *updated )
{
  GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Waypoint Properties"),
                                                   parent,
                                                   GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
                                                   GTK_STOCK_CANCEL,
                                                   GTK_RESPONSE_REJECT,
                                                   GTK_STOCK_OK,
                                                   GTK_RESPONSE_ACCEPT,
                                                   NULL);
  struct LatLon ll;
  GtkWidget *latlabel, *lonlabel, *namelabel, *latentry, *lonentry, *altentry, *altlabel, *nameentry=NULL;
  GtkWidget *commentlabel, *commententry, *descriptionlabel, *descriptionentry, *imagelabel, *imageentry, *symbollabel, *symbolentry;
  GtkWidget *sourcelabel = NULL, *sourceentry = NULL;
  GtkWidget *typelabel = NULL, *typeentry = NULL;
  GtkWidget *timelabel = NULL;
  GtkWidget *timevaluebutton = NULL;
  GtkWidget *hasGeotagCB = NULL;
  GtkWidget *consistentGeotagCB = NULL;
  GtkWidget *direction_sb = NULL;
  GtkWidget *direction_hb = NULL;
  GtkListStore *store;

  gchar *lat, *lon, *alt;

  vik_coord_to_latlon ( &(wp->coord), &ll );

  lat = g_strdup_printf ( "%f", ll.lat );
  lon = g_strdup_printf ( "%f", ll.lon );
  vik_units_height_t height_units = a_vik_get_units_height ();
  switch (height_units) {
  case VIK_UNITS_HEIGHT_METRES:
    alt = g_strdup_printf ( "%f", wp->altitude );
    break;
  case VIK_UNITS_HEIGHT_FEET:
    alt = g_strdup_printf ( "%f", VIK_METERS_TO_FEET(wp->altitude) );
    break;
  default:
    alt = g_strdup_printf ( "%f", wp->altitude );
    g_critical("Houston, we've had a problem. height=%d", height_units);
  }

  *updated = FALSE;

  namelabel = gtk_label_new (_("Name:"));
  gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), namelabel, FALSE, FALSE, 0);
  // Name is now always changeable
  nameentry = gtk_entry_new ();
  if ( default_name )
    gtk_entry_set_text( GTK_ENTRY(nameentry), default_name );
  g_signal_connect_swapped ( nameentry, "activate", G_CALLBACK(a_dialog_response_accept), GTK_DIALOG(dialog) );
  gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), nameentry, FALSE, FALSE, 0);

  latlabel = gtk_label_new (_("Latitude:"));
  latentry = gtk_entry_new ();
  gtk_entry_set_text ( GTK_ENTRY(latentry), lat );
  g_free ( lat );

  lonlabel = gtk_label_new (_("Longitude:"));
  lonentry = gtk_entry_new ();
  gtk_entry_set_text ( GTK_ENTRY(lonentry), lon );
  g_free ( lon );

  altlabel = gtk_label_new (_("Altitude:"));
  altentry = gtk_entry_new ();
  gtk_entry_set_text ( GTK_ENTRY(altentry), alt );
  g_free ( alt );

  if ( wp->comment && !strncmp(wp->comment, "http", 4) )
    commentlabel = gtk_link_button_new_with_label (wp->comment, _("Comment:") );
  else
    commentlabel = gtk_label_new (_("Comment:"));
  commententry = gtk_entry_new ();
  gchar *cmt =  NULL;
  // Auto put in some kind of 'name' as a comment if one previously 'goto'ed this exact location
  cmt = a_vik_goto_get_search_string_for_this_place(VIK_WINDOW(parent));
  if (cmt)
    gtk_entry_set_text(GTK_ENTRY(commententry), cmt);

  if ( wp->description && !strncmp(wp->description, "http", 4) )
    descriptionlabel = gtk_link_button_new_with_label (wp->description, _("Description:") );
  else
    descriptionlabel = gtk_label_new (_("Description:"));
  descriptionentry = gtk_entry_new ();

  sourcelabel = gtk_label_new (_("Source:"));
  if ( wp->source ) {
    sourceentry = gtk_entry_new ();
    gtk_entry_set_text(GTK_ENTRY(sourceentry), wp->source);
  }

  typelabel = gtk_label_new (_("Type:"));
  if ( wp->type ) {
    typeentry = gtk_entry_new ();
    gtk_entry_set_text(GTK_ENTRY(typeentry), wp->type);
  }

  imagelabel = gtk_label_new (_("Image:"));
  imageentry = vik_file_entry_new (GTK_FILE_CHOOSER_ACTION_OPEN, VF_FILTER_IMAGE, NULL, NULL);

  {
    GtkCellRenderer *r;
    symbollabel = gtk_label_new (_("Symbol:"));
    GtkTreeIter iter;

    store = gtk_list_store_new(3, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_STRING);
    symbolentry = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store));
    gtk_combo_box_set_wrap_width(GTK_COMBO_BOX(symbolentry), 6);

    g_signal_connect(symbolentry, "changed", G_CALLBACK(symbol_entry_changed_cb), store);
    gtk_list_store_append (store, &iter);
    gtk_list_store_set (store, &iter, 0, NULL, 1, NULL, 2, _("(none)"), -1);
    a_populate_sym_list(store);

    r = gtk_cell_renderer_pixbuf_new ();
    gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (symbolentry), r, FALSE);
    gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (symbolentry), r, "pixbuf", 1, NULL);

    r = gtk_cell_renderer_text_new ();
    gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (symbolentry), r, FALSE);
    gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (symbolentry), r, "text", 2, NULL);

    if ( !is_new && wp->symbol ) {
      gboolean ok;
      gchar *sym;
      for (ok = gtk_tree_model_get_iter_first ( GTK_TREE_MODEL(store), &iter ); ok; ok = gtk_tree_model_iter_next ( GTK_TREE_MODEL(store), &iter)) {
	gtk_tree_model_get ( GTK_TREE_MODEL(store), &iter, 0, (void *)&sym, -1 );
	if (sym && !strcmp(sym, wp->symbol)) {
	  g_free(sym);
	  break;
	} else {
	  g_free(sym);
	}
      }
      // Ensure is it a valid symbol in the given symbol set (large vs small)
      // Not all symbols are available in both
      // The check prevents a Gtk Critical message
      if ( iter.stamp )
	gtk_combo_box_set_active_iter(GTK_COMBO_BOX(symbolentry), &iter);
    }
  }

  if ( !is_new && wp->comment )
    gtk_entry_set_text ( GTK_ENTRY(commententry), wp->comment );

  if ( !is_new && wp->description )
    gtk_entry_set_text ( GTK_ENTRY(descriptionentry), wp->description );

  if ( !edit_wp )
    edit_wp = vik_waypoint_new ();
  edit_wp = vik_waypoint_copy ( wp );

  if ( !is_new && wp->image ) {
    vik_file_entry_set_filename ( VIK_FILE_ENTRY(imageentry), wp->image );

#ifdef VIK_CONFIG_GEOTAG
    // Geotag Info [readonly]
    hasGeotagCB = gtk_check_button_new_with_label ( _("Has Geotag") );
    gtk_widget_set_sensitive ( hasGeotagCB, FALSE );
    gboolean hasGeotag;
    gchar *ignore = a_geotag_get_exif_date_from_file ( wp->image, &hasGeotag );
    g_free ( ignore );
    gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(hasGeotagCB), hasGeotag );

    consistentGeotagCB = gtk_check_button_new_with_label ( _("Consistent Position") );
    gtk_widget_set_sensitive ( consistentGeotagCB, FALSE );
    if ( hasGeotag ) {
      struct LatLon ll = a_geotag_get_position ( wp->image );
      VikCoord coord;
      vik_coord_load_from_latlon ( &coord, coord_mode, &ll );
      gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(consistentGeotagCB), vik_coord_equalish(&coord, &wp->coord) );
    }

    // ATM the direction value box is always shown, even when there is no information.
    // It would be nice to be able to hide it until the 'Add' has been performed,
    //  however I've not been able to achieve this.
    // Thus simply sensistizing it instead.
    GtkWidget *direction_label = gtk_label_new ( _("Image Direction:") );
    direction_hb = gtk_hbox_new ( FALSE, 0 );
    gtk_box_pack_start (GTK_BOX(direction_hb), direction_label, FALSE, FALSE, 0);
    direction_sb = gtk_spin_button_new ( (GtkAdjustment*)gtk_adjustment_new (0, 0.0, 359.9, 5.0, 1, 0 ), 1, 1 );

    if ( !is_new && !isnan(wp->image_direction) ) {
      GtkWidget *direction_ref = gtk_label_new ( NULL );
      if ( wp->image_direction_ref == WP_IMAGE_DIRECTION_REF_MAGNETIC )
        gtk_label_set_label ( GTK_LABEL(direction_ref), _("Magnetic") );
      else
        gtk_label_set_label ( GTK_LABEL(direction_ref), _("True") );

      gtk_box_pack_start (GTK_BOX(direction_hb), direction_ref, TRUE, FALSE, 0);
      gtk_spin_button_set_value ( GTK_SPIN_BUTTON(direction_sb), wp->image_direction );
    }
    else {
      GtkWidget *direction_ref_button = gtk_button_new ();
      gtk_button_set_relief ( GTK_BUTTON(direction_ref_button), GTK_RELIEF_NONE );
      GtkWidget *img = gtk_image_new_from_stock ( GTK_STOCK_ADD, GTK_ICON_SIZE_MENU );
      gtk_button_set_image ( GTK_BUTTON(direction_ref_button), img );
      gtk_box_pack_start (GTK_BOX(direction_hb), direction_ref_button, TRUE, FALSE, 0);
      gtk_widget_set_sensitive ( direction_sb, FALSE );
      direction_signal_id = g_signal_connect ( G_OBJECT(direction_ref_button), "button-release-event", G_CALLBACK(direction_add_click), direction_sb );
    }

#endif
  }

  timelabel = gtk_label_new ( _("Time:") );
  timevaluebutton = gtk_button_new();
  gtk_button_set_relief ( GTK_BUTTON(timevaluebutton), GTK_RELIEF_NONE );

  // TODO: Consider if there should be a remove time button...

  if ( !is_new && wp->has_timestamp ) {
    update_time ( timevaluebutton, wp );
  }
  else {
    GtkWidget *img = gtk_image_new_from_stock ( GTK_STOCK_ADD, GTK_ICON_SIZE_MENU );
    gtk_button_set_image ( GTK_BUTTON(timevaluebutton), img );
    // Initially use current time or otherwise whatever the last value used was
    if ( edit_wp->timestamp == 0 ) {
      time ( &edit_wp->timestamp );
    }
  }
  g_signal_connect ( G_OBJECT(timevaluebutton), "button-release-event", G_CALLBACK(time_edit_click), edit_wp );

  gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), latlabel, FALSE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), latentry, FALSE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), lonlabel, FALSE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), lonentry, FALSE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), timelabel, FALSE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), timevaluebutton, FALSE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), altlabel, FALSE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), altentry, FALSE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), commentlabel, FALSE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), commententry, FALSE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), descriptionlabel, FALSE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), descriptionentry, FALSE, FALSE, 0);
  if ( wp->source ) {
    gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), sourcelabel, FALSE, FALSE, 0);
    gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), sourceentry, FALSE, FALSE, 0);
  }
  if ( wp->type ) {
    gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), typelabel, FALSE, FALSE, 0);
    gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), typeentry, FALSE, FALSE, 0);
  }
  gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), imagelabel, FALSE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), imageentry, FALSE, FALSE, 0);
  if ( hasGeotagCB ) {
    GtkWidget *hbox =  gtk_hbox_new ( FALSE, 0 );
    gtk_box_pack_start (GTK_BOX(hbox), hasGeotagCB, FALSE, FALSE, 0);
    gtk_box_pack_start (GTK_BOX(hbox), consistentGeotagCB, FALSE, FALSE, 0);
    gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), hbox, FALSE, FALSE, 0);
  }
  if ( direction_hb )
    gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), direction_hb, FALSE, FALSE, 0);
  if ( direction_sb )
    gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), direction_sb, FALSE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), symbollabel, FALSE, FALSE, 0);
  gtk_box_pack_start (GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), GTK_WIDGET(symbolentry), FALSE, FALSE, 0);

  gtk_dialog_set_default_response ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT );

  gtk_widget_show_all ( gtk_dialog_get_content_area(GTK_DIALOG(dialog)) );

  if ( !is_new ) {
    // Shift left<->right to try not to obscure the waypoint.
    trw_layer_dialog_shift ( vtl, GTK_WINDOW(dialog), &(wp->coord), FALSE );
  }

  while ( gtk_dialog_run ( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
  {
    if ( strlen((gchar*)gtk_entry_get_text ( GTK_ENTRY(nameentry) )) == 0 ) /* TODO: other checks (isalpha or whatever ) */
      a_dialog_info_msg ( parent, _("Please enter a name for the waypoint.") );
    else {
      // NB: No check for unique names - this allows generation of same named entries.
      gchar *entered_name = g_strdup ( (gchar*)gtk_entry_get_text ( GTK_ENTRY(nameentry) ) );

      /* Do It */
      ll.lat = convert_dms_to_dec ( gtk_entry_get_text ( GTK_ENTRY(latentry) ) );
      ll.lon = convert_dms_to_dec ( gtk_entry_get_text ( GTK_ENTRY(lonentry) ) );
      vik_coord_load_from_latlon ( &(wp->coord), coord_mode, &ll );
      // Always store in metres
      switch (height_units) {
      case VIK_UNITS_HEIGHT_METRES:
        wp->altitude = atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) );
        break;
      case VIK_UNITS_HEIGHT_FEET:
        wp->altitude = VIK_FEET_TO_METERS(atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) ));
        break;
      default:
        wp->altitude = atof ( gtk_entry_get_text ( GTK_ENTRY(altentry) ) );
        g_critical("Houston, we've had a problem. height=%d", height_units);
      }
      if ( g_strcmp0 ( wp->comment, gtk_entry_get_text ( GTK_ENTRY(commententry) ) ) )
        vik_waypoint_set_comment ( wp, gtk_entry_get_text ( GTK_ENTRY(commententry) ) );
      if ( g_strcmp0 ( wp->description, gtk_entry_get_text ( GTK_ENTRY(descriptionentry) ) ) )
        vik_waypoint_set_description ( wp, gtk_entry_get_text ( GTK_ENTRY(descriptionentry) ) );
      if ( g_strcmp0 ( wp->image, vik_file_entry_get_filename ( VIK_FILE_ENTRY(imageentry) ) ) )
        vik_waypoint_set_image ( wp, vik_file_entry_get_filename ( VIK_FILE_ENTRY(imageentry) ) );
      if ( sourceentry && g_strcmp0 ( wp->source, gtk_entry_get_text ( GTK_ENTRY(sourceentry) ) ) )
        vik_waypoint_set_source ( wp, gtk_entry_get_text ( GTK_ENTRY(sourceentry) ) );
      if ( typeentry && g_strcmp0 ( wp->type, gtk_entry_get_text ( GTK_ENTRY(typeentry) ) ) )
        vik_waypoint_set_type ( wp, gtk_entry_get_text ( GTK_ENTRY(typeentry) ) );
      if ( wp->image && *(wp->image) && (!a_thumbnails_exists(wp->image)) )
        a_thumbnails_create ( wp->image );
      if ( edit_wp->timestamp ) {
        wp->timestamp = edit_wp->timestamp;
        wp->has_timestamp = TRUE;
      }

      if ( direction_sb ) {
        if ( gtk_widget_get_sensitive (direction_sb) ) {
          wp->image_direction = gtk_spin_button_get_value ( GTK_SPIN_BUTTON(direction_sb) );
          if ( wp->image_direction != edit_wp->image_direction )
            a_geotag_write_exif_gps ( wp->image, wp->coord, wp->altitude, wp->image_direction, wp->image_direction_ref, TRUE );
        }
      }

      GtkTreeIter iter, first;
      gtk_tree_model_get_iter_first ( GTK_TREE_MODEL(store), &first );
      if ( !gtk_combo_box_get_active_iter ( GTK_COMBO_BOX(symbolentry), &iter ) || !memcmp(&iter, &first, sizeof(GtkTreeIter)) ) {
        vik_waypoint_set_symbol ( wp, NULL );
      } else {
        gchar *sym;
        gtk_tree_model_get ( GTK_TREE_MODEL(store), &iter, 0, (void *)&sym, -1 );
        vik_waypoint_set_symbol ( wp, sym );
        g_free(sym);
      }

      gtk_widget_destroy ( dialog );
      if ( is_new )
        return entered_name;
      else {
        *updated = TRUE;
        // See if name has been changed
        if ( g_strcmp0 (default_name, entered_name ) )
          return entered_name;
        else
          return NULL;
      }
    }
  }
  gtk_widget_destroy ( dialog );
  return NULL;
}
예제 #3
0
/**
 * Automatic attempt to find out where you are using:
 *   1. http://www.hostip.info ++
 *   2. if not specific enough fallback to using the default goto tool with a country name
 * ++ Using returned JSON information
 *  c.f. with googlesearch.c - similar implementation is used here
 *
 * returns:
 *   0 if failed to locate anything
 *   1 if exact latitude/longitude found
 *   2 if position only as precise as a city
 *   3 if position only as precise as a country
 * @name: Contains the name of place found. Free this string after use.
 */
gint a_vik_goto_where_am_i ( VikViewport *vvp, struct LatLon *ll, gchar **name )
{
  gint result = 0;
  *name = NULL;

  gchar *tmpname = a_download_uri_to_tmp_file ( "http://api.hostip.info/get_json.php?position=true", NULL );
  //gchar *tmpname = g_strdup ("../test/hostip2.json");
  if (!tmpname) {
    return result;
  }

  ll->lat = 0.0;
  ll->lon = 0.0;

  gchar *pat;
  GMappedFile *mf;
  gchar *ss;
  gint fragment_len;

  gchar lat_buf[32], lon_buf[32];
  lat_buf[0] = lon_buf[0] = '\0';
  gchar *country = NULL;
  gchar *city = NULL;

  if ((mf = g_mapped_file_new(tmpname, FALSE, NULL)) == NULL) {
    g_critical(_("couldn't map temp file"));
    goto tidy;
  }

  gsize len = g_mapped_file_get_length(mf);
  gchar *text = g_mapped_file_get_contents(mf);

  if ((pat = g_strstr_len(text, len, HOSTIP_COUNTRY_PATTERN))) {
    pat += strlen(HOSTIP_COUNTRY_PATTERN);
    fragment_len = 0;
    ss = pat;
    while (*pat != '"') {
      fragment_len++;
      pat++;
    }
    country = g_strndup(ss, fragment_len);
  }

  if ((pat = g_strstr_len(text, len, HOSTIP_CITY_PATTERN))) {
    pat += strlen(HOSTIP_CITY_PATTERN);
    fragment_len = 0;
    ss = pat;
    while (*pat != '"') {
      fragment_len++;
      pat++;
    }
    city = g_strndup(ss, fragment_len);
  }

  if ((pat = g_strstr_len(text, len, HOSTIP_LATITUDE_PATTERN))) {
    pat += strlen(HOSTIP_LATITUDE_PATTERN);
    ss = lat_buf;
    if (*pat == '-')
      *ss++ = *pat++;
    while ((ss < (lat_buf + sizeof(lat_buf))) && (pat < (text + len)) &&
	   (g_ascii_isdigit(*pat) || (*pat == '.')))
      *ss++ = *pat++;
    *ss = '\0';
    ll->lat = g_ascii_strtod(lat_buf, NULL);
  }

  if ((pat = g_strstr_len(text, len, HOSTIP_LONGITUDE_PATTERN))) {
    pat += strlen(HOSTIP_LONGITUDE_PATTERN);
    ss = lon_buf;
    if (*pat == '-')
      *ss++ = *pat++;
    while ((ss < (lon_buf + sizeof(lon_buf))) && (pat < (text + len)) &&
	   (g_ascii_isdigit(*pat) || (*pat == '.')))
      *ss++ = *pat++;
    *ss = '\0';
    ll->lon = g_ascii_strtod(lon_buf, NULL);
  }

  if ( ll->lat != 0.0 && ll->lon != 0.0 ) {
    if ( ll->lat > -90.0 && ll->lat < 90.0 && ll->lon > -180.0 && ll->lon < 180.0 ) {
      // Found a 'sensible' & 'precise' location
      result = 1;
      *name = g_strdup ( _("Locality") ); //Albeit maybe not known by an actual name!
    }
  }
  else {
    // Hopefully city name is unique enough to lookup position on
    // Maybe for American places where hostip appends the State code on the end
    // But if the country code is not appended if could easily get confused
    //  e.g. 'Portsmouth' could be at least
    //   Portsmouth, Hampshire, UK or
    //   Portsmouth, Viginia, USA.

    // Try city name lookup
    if ( city ) {
      g_debug ( "%s: found city %s", __FUNCTION__, city );
      if ( strcmp ( city, "(Unknown city)" ) != 0 ) {
        VikCoord new_center;
        if ( vik_goto_place ( NULL, vvp, city, &new_center ) ) {
          // Got something
          vik_coord_to_latlon ( &new_center, ll );
          result = 2;
          *name = city;
          goto tidy;
        }
      }
    }

    // Try country name lookup
    if ( country ) {
      g_debug ( "%s: found country %s", __FUNCTION__, country );
      if ( strcmp ( country, "(Unknown Country)" ) != 0 ) {
        VikCoord new_center;
        if ( vik_goto_place ( NULL, vvp, country, &new_center ) ) {
          // Finally got something
          vik_coord_to_latlon ( &new_center, ll );
          result = 3;
          *name = country;
          goto tidy;
        }
      }
    }
  }
  
 tidy:
  g_mapped_file_unref ( mf );
  g_remove ( tmpname );
  g_free ( tmpname );
  return result;
}
static gboolean dem_layer_download_release ( VikDEMLayer *vdl, GdkEventButton *event, VikViewport *vvp )
{
  VikCoord coord;
  static struct LatLon ll;

  gchar *full_path;
  gchar *dem_file = NULL;

  vik_viewport_screen_to_coord ( vvp, event->x, event->y, &coord );
  vik_coord_to_latlon ( &coord, &ll );

  
  if ( vdl->source == DEM_SOURCE_SRTM )
    dem_file = srtm_lat_lon_to_dest_fn ( ll.lat, ll.lon );
#ifdef VIK_CONFIG_DEM24K
  else if ( vdl->source == DEM_SOURCE_DEM24K )
    dem_file = dem24k_lat_lon_to_dest_fn ( ll.lat, ll.lon );
#endif

  if ( ! dem_file )
    return TRUE;

  full_path = g_strdup_printf("%s%s", MAPS_CACHE_DIR, dem_file );

  g_debug("%s: %s", __FUNCTION__, full_path);

  if ( event->button == 1 ) {
    // TODO: check if already in filelist
    if ( ! dem_layer_add_file(vdl, full_path) ) {
      gchar *tmp = g_strdup_printf ( _("Downloading DEM %s"), dem_file );
      DEMDownloadParams *p = g_malloc(sizeof(DEMDownloadParams));
      p->dest = g_strdup(full_path);
      p->lat = ll.lat;
      p->lon = ll.lon;
      p->vdl = vdl;
      p->mutex = g_mutex_new();
      p->source = vdl->source;
      g_object_weak_ref(G_OBJECT(p->vdl), weak_ref_cb, p );

      a_background_thread ( VIK_GTK_WINDOW_FROM_LAYER(vdl), tmp,
                            (vik_thr_func) dem_download_thread, p,
                            (vik_thr_free_func) free_dem_download_params, NULL, 1 );

      g_free ( tmp );
    }
    else
      vik_layer_emit_update ( VIK_LAYER(vdl) );
  }
  else {
    if ( !vdl->right_click_menu ) {
      GtkWidget *item;
      vdl->right_click_menu = GTK_MENU ( gtk_menu_new () );

      item = gtk_image_menu_item_new_with_mnemonic ( _("_Show DEM File Information") );
      gtk_image_menu_item_set_image ( (GtkImageMenuItem*)item, gtk_image_new_from_stock (GTK_STOCK_INFO, GTK_ICON_SIZE_MENU) );
      g_signal_connect ( G_OBJECT(item), "activate", G_CALLBACK(dem_layer_file_info), &ll );
      gtk_menu_shell_append (GTK_MENU_SHELL(vdl->right_click_menu), item);
    }

    gtk_menu_popup ( vdl->right_click_menu, NULL, NULL, NULL, NULL, event->button, event->time );
    gtk_widget_show_all ( GTK_WIDGET(vdl->right_click_menu) );
  }

  g_free ( dem_file );
  g_free ( full_path );

  return TRUE;
}
예제 #5
0
파일: gpspoint.c 프로젝트: apre/viking
static void a_gpspoint_write_trackpoint ( VikTrackpoint *tp, TP_write_info_type *write_info )
{
  struct LatLon ll;
  gchar s_lat[COORDS_STR_BUFFER_SIZE];
  gchar s_lon[COORDS_STR_BUFFER_SIZE];
  gchar s_alt[COORDS_STR_BUFFER_SIZE];
  vik_coord_to_latlon ( &(tp->coord), &ll );

  FILE *f = write_info->f;

  a_coords_dtostr_buffer ( ll.lat, s_lat );
  a_coords_dtostr_buffer ( ll.lon, s_lon );
  fprintf ( f, "type=\"%spoint\" latitude=\"%s\" longitude=\"%s\"", write_info->is_route ? "route" : "track", s_lat, s_lon );

  if ( tp->name ) {
    gchar *name = slashdup(tp->name);
    fprintf ( f, " name=\"%s\"", name );
    g_free(name);
  }

  if ( tp->altitude != VIK_DEFAULT_ALTITUDE ) {
    a_coords_dtostr_buffer ( tp->altitude, s_alt );
    fprintf ( f, " altitude=\"%s\"", s_alt );
  }
  if ( tp->has_timestamp )
    fprintf ( f, " unixtime=\"%ld\"", tp->timestamp );
  if ( tp->newsegment )
    fprintf ( f, " newsegment=\"yes\"" );

  if (!isnan(tp->speed) || !isnan(tp->course) || tp->nsats > 0) {
    fprintf ( f, " extended=\"yes\"" );
    if (!isnan(tp->speed)) {
      gchar s_speed[COORDS_STR_BUFFER_SIZE];
      a_coords_dtostr_buffer ( tp->speed, s_speed );
      fprintf ( f, " speed=\"%s\"", s_speed );
    }
    if (!isnan(tp->course)) {
      gchar s_course[COORDS_STR_BUFFER_SIZE];
      a_coords_dtostr_buffer ( tp->course, s_course );
      fprintf ( f, " course=\"%s\"", s_course );
    }
    if (tp->nsats > 0)
      fprintf ( f, " sat=\"%d\"", tp->nsats );
    if (tp->fix_mode > 0)
      fprintf ( f, " fix=\"%d\"", tp->fix_mode );

    if ( tp->hdop != VIK_DEFAULT_DOP ) {
      gchar ss[COORDS_STR_BUFFER_SIZE];
      a_coords_dtostr_buffer ( tp->hdop, ss );
      fprintf ( f, " hdop=\"%s\"", ss );
    }
    if ( tp->vdop != VIK_DEFAULT_DOP ) {
      gchar ss[COORDS_STR_BUFFER_SIZE];
      a_coords_dtostr_buffer ( tp->vdop, ss );
      fprintf ( f, " vdop=\"%s\"", ss );
    }
    if ( tp->pdop != VIK_DEFAULT_DOP ) {
      gchar ss[COORDS_STR_BUFFER_SIZE];
      a_coords_dtostr_buffer ( tp->pdop, ss );
      fprintf ( f, " pdop=\"%s\"", ss );
    }
  }
  fprintf ( f, "\n" );
}
예제 #6
0
파일: gpspoint.c 프로젝트: apre/viking
static void a_gpspoint_write_waypoint ( const gpointer id, const VikWaypoint *wp, FILE *f )
{
  struct LatLon ll;
  gchar s_lat[COORDS_STR_BUFFER_SIZE];
  gchar s_lon[COORDS_STR_BUFFER_SIZE];
  // Sanity clauses
  if ( !wp )
    return;
  if ( !(wp->name) )
    return;

  vik_coord_to_latlon ( &(wp->coord), &ll );
  a_coords_dtostr_buffer ( ll.lat, s_lat );
  a_coords_dtostr_buffer ( ll.lon, s_lon );
  gchar *tmp_name = slashdup(wp->name);
  fprintf ( f, "type=\"waypoint\" latitude=\"%s\" longitude=\"%s\" name=\"%s\"", s_lat, s_lon, tmp_name );
  g_free ( tmp_name );

  if ( wp->altitude != VIK_DEFAULT_ALTITUDE ) {
    gchar s_alt[COORDS_STR_BUFFER_SIZE];
    a_coords_dtostr_buffer ( wp->altitude, s_alt );
    fprintf ( f, " altitude=\"%s\"", s_alt );
  }
  if ( wp->has_timestamp )
    fprintf ( f, " unixtime=\"%ld\"", wp->timestamp );
  if ( wp->comment )
  {
    gchar *tmp_comment = slashdup(wp->comment);
    fprintf ( f, " comment=\"%s\"", tmp_comment );
    g_free ( tmp_comment );
  }
  if ( wp->description )
  {
    gchar *tmp_description = slashdup(wp->description);
    fprintf ( f, " description=\"%s\"", tmp_description );
    g_free ( tmp_description );
  }
  if ( wp->source )
  {
    gchar *tmp_source = slashdup(wp->source);
    fprintf ( f, " source=\"%s\"", tmp_source );
    g_free ( tmp_source );
  }
  if ( wp->type )
  {
    gchar *tmp_type = slashdup(wp->type);
    fprintf ( f, " xtype=\"%s\"", tmp_type );
    g_free ( tmp_type );
  }
  if ( wp->image )
  {
    gchar *tmp_image = NULL;
    gchar *cwd = NULL;
    if ( a_vik_get_file_ref_format() == VIK_FILE_REF_FORMAT_RELATIVE ) {
      cwd = g_get_current_dir();
      if ( cwd )
        tmp_image = g_strdup ( file_GetRelativeFilename ( cwd, wp->image ) );
    }

    // if cwd not available - use image filename as is
    // this should be an absolute path as set in thumbnails
    if ( !cwd )
      tmp_image = slashdup(wp->image);

    if ( tmp_image )
      fprintf ( f, " image=\"%s\"", tmp_image );

    g_free ( cwd );
    g_free ( tmp_image );
  }
  if ( wp->symbol )
  {
    // Due to changes in garminsymbols - the symbol name is now in Title Case
    // However to keep newly generated .vik files better compatible with older Viking versions
    //   The symbol names will always be lowercase
    gchar *tmp_symbol = g_utf8_strdown(wp->symbol, -1);
    fprintf ( f, " symbol=\"%s\"", tmp_symbol );
    g_free ( tmp_symbol );
  }
  if ( ! wp->visible )
    fprintf ( f, " visible=\"n\"" );
  fprintf ( f, "\n" );
}
예제 #7
0
파일: vikutils.c 프로젝트: idaohang/viking
/**
 * vu_trackpoint_formatted_message:
 * @format_code:  String describing the message to generate
 * @trkpt:        The trackpoint for which the message is generated about
 * @trkpt_prev:   A trackpoint (presumed previous) for interpolating values with the other trackpoint (such as speed)
 * @trk:          The track in which the trackpoints reside
 * @climb:        Vertical speed (Out of band (i.e. not in a trackpoint) value for display currently only for GPSD usage)
 *
 *  TODO: One day replace this cryptic format code with some kind of tokenizer parsing
 *    thus would make it more user friendly and maybe even GUI controlable.
 * However for now at least there is some semblance of user control
 */
gchar* vu_trackpoint_formatted_message ( gchar *format_code, VikTrackpoint *trkpt, VikTrackpoint *trkpt_prev, VikTrack *trk, gdouble climb )
{
	if ( !trkpt )
		return NULL;

	gint len = 0;
	if ( format_code )
		len = strlen ( format_code );
	if ( len > FMT_MAX_NUMBER_CODES )
		len = FMT_MAX_NUMBER_CODES;

	gchar* values[FMT_MAX_NUMBER_CODES];
	int i;
	for ( i = 0; i < FMT_MAX_NUMBER_CODES; i++ ) {
		values[i] = '\0';
	}

	gchar *speed_units_str = NULL;
	vik_units_speed_t speed_units = a_vik_get_units_speed ();
	switch (speed_units) {
	case VIK_UNITS_SPEED_MILES_PER_HOUR:
		speed_units_str = g_strdup ( _("mph") );
		break;
	case VIK_UNITS_SPEED_METRES_PER_SECOND:
		speed_units_str = g_strdup ( _("m/s") );
		break;
	case VIK_UNITS_SPEED_KNOTS:
		speed_units_str = g_strdup ( _("knots") );
		break;
	default:
		// VIK_UNITS_SPEED_KILOMETRES_PER_HOUR:
		speed_units_str = g_strdup ( _("km/h") );
		break;
	}

	gchar *separator = g_strdup ( " | " );

	for ( i = 0; i < len; i++ ) {
		switch ( g_ascii_toupper ( format_code[i] ) ) {
		case 'G': values[i] = g_strdup ( _("GPSD") ); break; // GPS Preamble
		case 'K': values[i] = g_strdup ( _("Trkpt") ); break; // Trkpt Preamble

		case 'S': {
			gdouble speed = 0.0;
			gchar *speedtype = NULL;
			if ( isnan(trkpt->speed) && trkpt_prev ) {
				if ( trkpt->has_timestamp && trkpt_prev->has_timestamp ) {
					if ( trkpt->timestamp != trkpt_prev->timestamp ) {

						// Work out from previous trackpoint location and time difference
						speed = vik_coord_diff(&(trkpt->coord), &(trkpt_prev->coord)) / ABS(trkpt->timestamp - trkpt_prev->timestamp);
						speedtype = g_strdup ( "*" ); // Interpolated
					}
					else
						speedtype = g_strdup ( "**" );
				}
				else
					speedtype = g_strdup ( "**" );
			}
			else {
				speed = trkpt->speed;
				speedtype = g_strdup ( "" );
			}
			switch (speed_units) {
			case VIK_UNITS_SPEED_KILOMETRES_PER_HOUR:
				speed = VIK_MPS_TO_KPH(speed);
				break;
			case VIK_UNITS_SPEED_MILES_PER_HOUR:
				speed = VIK_MPS_TO_MPH(speed);
				break;
			case VIK_UNITS_SPEED_KNOTS:
				speed = VIK_MPS_TO_KNOTS(speed);
				break;
			default:
				// VIK_UNITS_SPEED_METRES_PER_SECOND:
				// Already in m/s so nothing to do
				break;
			}

			values[i] = g_strdup_printf ( _("%sSpeed%s %.1f%s"), separator, speedtype, speed, speed_units_str );
			g_free ( speedtype );
			break;
		}

		case 'B': {
			gdouble speed = 0.0;
			gchar *speedtype = NULL;
			if ( isnan(climb) && trkpt_prev ) {
				if ( trkpt->has_timestamp && trkpt_prev->has_timestamp ) {
					if ( trkpt->timestamp != trkpt_prev->timestamp ) {
						// Work out from previous trackpoint altitudes and time difference
						// 'speed' can be negative if going downhill
						speed = (trkpt->altitude - trkpt_prev->altitude) / ABS(trkpt->timestamp - trkpt_prev->timestamp);
						speedtype = g_strdup ( "*" ); // Interpolated
					}
					else
						speedtype = g_strdup ( "**" ); // Unavailable
				}
				else
					speedtype = g_strdup ( "**" );
			}
			else {
				speed = climb;
				speedtype = g_strdup ( "" );
			}
			switch (speed_units) {
			case VIK_UNITS_SPEED_KILOMETRES_PER_HOUR:
				speed = VIK_MPS_TO_KPH(speed);
				break;
			case VIK_UNITS_SPEED_MILES_PER_HOUR:
				speed = VIK_MPS_TO_MPH(speed);
				break;
			case VIK_UNITS_SPEED_KNOTS:
				speed = VIK_MPS_TO_KNOTS(speed);
				break;
			default:
				// VIK_UNITS_SPEED_METRES_PER_SECOND:
				// Already in m/s so nothing to do
				break;
			}
			// Go for 2dp as expect low values for vertical speeds
			values[i] = g_strdup_printf ( _("%sClimb%s %.2f%s"), separator, speedtype, speed, speed_units_str );
			g_free ( speedtype );
			break;
		}

		case 'A': {
			vik_units_height_t height_units = a_vik_get_units_height ();
			switch (height_units) {
			case VIK_UNITS_HEIGHT_FEET:
				values[i] = g_strdup_printf ( _("%sAlt %dfeet"), separator, (int)round(VIK_METERS_TO_FEET(trkpt->altitude)) );
				break;
			default:
				//VIK_UNITS_HEIGHT_METRES:
				values[i] = g_strdup_printf ( _("%sAlt %dm"), separator, (int)round(trkpt->altitude) );
				break;
			}
			break;
		}

		case 'C': {
			gint heading = isnan(trkpt->course) ? 0 : (gint)round(trkpt->course);
			values[i] = g_strdup_printf ( _("%sCourse %03d\302\260" ), separator, heading );
			break;
		}

		case 'P': {
			if ( trkpt_prev ) {
				gint diff = (gint) round ( vik_coord_diff ( &(trkpt->coord), &(trkpt_prev->coord) ) );

				gchar *dist_units_str = NULL;
				vik_units_distance_t dist_units = a_vik_get_units_distance ();
				// expect the difference between track points to be small hence use metres or yards
				switch (dist_units) {
				case VIK_UNITS_DISTANCE_MILES:
				case VIK_UNITS_DISTANCE_NAUTICAL_MILES:
					dist_units_str = g_strdup ( _("yards") );
					break;
				default:
					// VIK_UNITS_DISTANCE_KILOMETRES:
					dist_units_str = g_strdup ( _("m") );
					break;
				}

				values[i] = g_strdup_printf ( _("%sDistance diff %d%s"), separator, diff, dist_units_str );

				g_free ( dist_units_str );
			}
			break;
		}

		case 'T': {
			gchar *msg;
			if ( trkpt->has_timestamp ) {
				// Compact date time format
				msg = vu_get_time_string ( &(trkpt->timestamp), "%x %X", &(trkpt->coord), NULL );
			}
			else
				msg = g_strdup ("--");
			values[i] = g_strdup_printf ( _("%sTime %s"), separator, msg );
			g_free ( msg );
			break;
		}

		case 'M': {
			if ( trkpt_prev ) {
				if ( trkpt->has_timestamp && trkpt_prev->has_timestamp ) {
					time_t t_diff = trkpt->timestamp - trkpt_prev->timestamp;
					values[i] = g_strdup_printf ( _("%sTime diff %lds"), separator, t_diff );
				}
			}
			break;
		}

		case 'X': values[i] = g_strdup_printf ( _("%sNo. of Sats %d"), separator, trkpt->nsats ); break;

		case 'F': {
			if ( trk ) {
				// Distance to the end 'Finish' (along the track)
				gdouble distd =	vik_track_get_length_to_trackpoint (trk, trkpt);
				gdouble diste =	vik_track_get_length_including_gaps ( trk );
				gdouble dist = diste - distd;
				gchar *dist_units_str = NULL;
				vik_units_distance_t dist_units = a_vik_get_units_distance ();
				switch (dist_units) {
				case VIK_UNITS_DISTANCE_MILES:
					dist_units_str = g_strdup ( _("miles") );
					dist = VIK_METERS_TO_MILES(dist);
					break;
				case VIK_UNITS_DISTANCE_NAUTICAL_MILES:
					dist_units_str = g_strdup ( _("NM") );
					dist = VIK_METERS_TO_NAUTICAL_MILES(dist);
					break;
				default:
					// VIK_UNITS_DISTANCE_KILOMETRES:
					dist_units_str = g_strdup ( _("km") );
					dist = dist / 1000.0;
					break;
				}
				values[i] = g_strdup_printf ( _("%sTo End %.2f%s"), separator, dist, dist_units_str );
				g_free ( dist_units_str );
			}
			break;
		}

		case 'D': {
			if ( trk ) {
				// Distance from start (along the track)
				gdouble distd =	vik_track_get_length_to_trackpoint (trk, trkpt);
				gchar *dist_units_str = NULL;
				vik_units_distance_t dist_units = a_vik_get_units_distance ();
				switch (dist_units) {
				case VIK_UNITS_DISTANCE_MILES:
					dist_units_str = g_strdup ( _("miles") );
					distd = VIK_METERS_TO_MILES(distd);
					break;
				case VIK_UNITS_DISTANCE_NAUTICAL_MILES:
					dist_units_str = g_strdup ( _("NM") );
					distd = VIK_METERS_TO_NAUTICAL_MILES(distd);
					break;
				default:
					// VIK_UNITS_DISTANCE_KILOMETRES:
					dist_units_str = g_strdup ( _("km") );
					distd = distd / 1000.0;
					break;
				}
				values[i] = g_strdup_printf ( _("%sDistance along %.2f%s"), separator, distd, dist_units_str );
				g_free ( dist_units_str );
			}
			break;
		}

		case 'L': {
			// Location (Lat/Long)
			gchar *lat = NULL, *lon = NULL;
			struct LatLon ll;
			vik_coord_to_latlon (&(trkpt->coord), &ll);
			a_coords_latlon_to_string ( &ll, &lat, &lon );
			values[i] = g_strdup_printf ( "%s%s %s", separator, lat, lon );
			g_free ( lat );
			g_free ( lon );
			break;
		}

		case 'N': // Name of track
			values[i] = g_strdup_printf ( _("%sTrack: %s"), separator, trk->name );
			break;

		case 'E': // Name of trackpoint if available
			if ( trkpt->name )
				values[i] = g_strdup_printf ( "%s%s", separator, trkpt->name );
			else
				values[i] = g_strdup ( "" );
			break;

		default:
			break;
		}
	}

	g_free ( separator );
	g_free ( speed_units_str );

	gchar *msg = g_strconcat ( values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7], values[8], NULL );

	for ( i = 0; i < FMT_MAX_NUMBER_CODES; i++ ) {
		if ( values[i] != '\0' )
			g_free ( values[i] );
	}
	
	return msg;
}
예제 #8
0
파일: geotag_exif.c 프로젝트: guyou/viking
/**
 * a_geotag_write_exif_gps:
 * @filename: The image file to save information in
 * @coord:    The location
 * @alt:      The elevation
 * @direction:     The image direction (if NAN then these direction fields are not written)
 * @direction_ref: The image direction value type
 *
 * Returns: A value indicating success: 0, or some other value for failure
 *
 */
gint a_geotag_write_exif_gps ( const gchar *filename, VikCoord coord, gdouble alt,
                               gdouble direction, VikWaypointImageDirectionRef direction_ref,
                               gboolean no_change_mtime )
{
	gint result = 0; // OK so far...

	// Save mtime for later use
	struct stat stat_save;
	if ( no_change_mtime )
		if ( stat ( filename, &stat_save ) != 0 )
			g_warning ( "%s couldn't read: %s", __FUNCTION__, filename );

#ifdef HAVE_LIBGEXIV2
	GExiv2Metadata *gemd = gexiv2_metadata_new ();
	if ( gexiv2_metadata_open_path ( gemd, filename, NULL ) ) {
		struct LatLon ll;
		vik_coord_to_latlon ( &coord, &ll );
		if ( ! gexiv2_metadata_set_gps_info ( gemd, ll.lon, ll.lat, alt ) ) {
			result = 1; // Failed
		}
		else {
			if ( !isnan(direction) ) {
				gint nom = (gint)round(direction * 10.0);
				gboolean set_d = gexiv2_metadata_set_exif_tag_rational ( gemd, EXIF_GPS_IMGDIR, nom, 10 );
				if ( !set_d ) result = 1; // Failed
				gboolean set_r = gexiv2_metadata_set_tag_string ( gemd, EXIF_GPS_IMGDIR_REF, direction_ref == WP_IMAGE_DIRECTION_REF_TRUE ? "T" : "M" );
				if ( !set_r ) result = 1; // Failed
			}
			// Still OK to save - no fails yet
			if ( result == 0 ) {
				GError *error = NULL;
				if ( ! gexiv2_metadata_save_file ( gemd, filename, &error ) ) {
					result = 2;
					g_warning ( "Write EXIF failure:%s" , error->message );
					g_error_free ( error );
				}
			}
		}
	}
	metadata_free ( gemd );
#else
#ifdef HAVE_LIBEXIF
	/*
	  Appears libexif doesn't actually support writing EXIF data directly to files
	  Thus embed command line exif writing method within Viking
	  (for example this is done by Enlightment - http://www.enlightenment.org/ )
	  This appears to be JPEG only, but is probably 99% of our use case
	  Alternatively consider using libexiv2 and C++...
	*/

	// Actual EXIF settings here...
	JPEGData *jdata;

	/* Parse the JPEG file. */
	jdata = jpeg_data_new ();
	jpeg_data_load_file (jdata, filename);

	// Get current values
	ExifData *ed = exif_data_new_from_file ( filename );
	if ( !ed )
		ed = exif_data_new ();

	// Update ExifData with our new settings
	ExifEntry *ee;
	//
	// I don't understand it, but when saving the 'ed' nothing gets set after putting in the GPS ID tag - so it must come last
	// (unless of course there is some bug in the setting of the ID, that prevents subsequent tags)
	//

	ee = my_exif_create_value (ed, EXIF_TAG_GPS_ALTITUDE, EXIF_IFD_GPS);
	convert_to_entry ( NULL, alt, ee, exif_data_get_byte_order(ed) );

	// byte 0 meaning "sea level" or 1 if the value is negative.
	ee = my_exif_create_value (ed, EXIF_TAG_GPS_ALTITUDE_REF, EXIF_IFD_GPS);
	convert_to_entry ( alt < 0.0 ? "1" : "0", 0.0, ee, exif_data_get_byte_order(ed) );

	ee = my_exif_create_value (ed, EXIF_TAG_GPS_PROCESSING_METHOD, EXIF_IFD_GPS);
	// see http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/GPS.html
	convert_to_entry ( "MANUAL", 0.0, ee, exif_data_get_byte_order(ed) );

	ee = my_exif_create_value (ed, EXIF_TAG_GPS_MAP_DATUM, EXIF_IFD_GPS);
	convert_to_entry ( "WGS-84", 0.0, ee, exif_data_get_byte_order(ed) );

	struct LatLon ll;
    vik_coord_to_latlon ( &coord, &ll );

	ee = my_exif_create_value (ed, EXIF_TAG_GPS_LATITUDE_REF, EXIF_IFD_GPS);
	// N or S
	convert_to_entry ( ll.lat < 0.0 ? "S" : "N", 0.0, ee, exif_data_get_byte_order(ed) );

	ee = my_exif_create_value (ed, EXIF_TAG_GPS_LATITUDE, EXIF_IFD_GPS);
	convert_to_entry ( NULL, ll.lat, ee, exif_data_get_byte_order(ed) );

	ee = my_exif_create_value (ed, EXIF_TAG_GPS_LONGITUDE_REF, EXIF_IFD_GPS);
	// E or W
	convert_to_entry ( ll.lon < 0.0 ? "W" : "E", 0.0, ee, exif_data_get_byte_order(ed) );

	ee = my_exif_create_value (ed, EXIF_TAG_GPS_LONGITUDE, EXIF_IFD_GPS);
	convert_to_entry ( NULL, ll.lon, ee, exif_data_get_byte_order(ed) );

	ee = my_exif_create_value (ed, EXIF_TAG_GPS_VERSION_ID, EXIF_IFD_GPS);
	//convert_to_entry ( "2 0 0 0", 0.0, ee, exif_data_get_byte_order(ed) );
	convert_to_entry ( "2 2 0 0", 0.0, ee, exif_data_get_byte_order(ed) );

	jpeg_data_set_exif_data (jdata, ed);

	if ( jdata ) {
		/* Save the modified image. */
		result = jpeg_data_save_file (jdata, filename);

		// Convert result from 1 for success, 0 for failure into our scheme
		result = !result;
		
		jpeg_data_unref (jdata);
	}
	else {
		// Epic fail - file probably not a JPEG
		result = 2;
	}

	exif_data_free ( ed );
#endif
#endif

	if ( no_change_mtime ) {
		// Restore mtime, using the saved value
		struct stat stat_tmp;
		struct utimbuf utb;
		(void)stat ( filename, &stat_tmp );
		utb.actime = stat_tmp.st_atime;
		utb.modtime = stat_save.st_mtime;
		// Not security critical, thus potential Time of Check Time of Use race condition is not bad
		// coverity[toctou]
		if ( g_utime ( filename, &utb ) != 0 )
			g_warning ( "%s couldn't set time on: %s", __FUNCTION__, filename );
	}

	return result;
}
예제 #9
0
파일: gpx.c 프로젝트: idaohang/viking-1
static void gpx_write_trackpoint ( VikTrackpoint *tp, GpxWritingContext *context )
{
  FILE *f = context->file;
  static struct LatLon ll;
  gchar *s_lat,*s_lon, *s_alt, *s_dop;
  gchar *time_iso8601;
  vik_coord_to_latlon ( &(tp->coord), &ll );

  if ( tp->newsegment )
    fprintf ( f, "  </trkseg>\n  <trkseg>\n" );

  s_lat = a_coords_dtostr( ll.lat );
  s_lon = a_coords_dtostr( ll.lon );
  fprintf ( f, "  <trkpt lat=\"%s\" lon=\"%s\">\n", s_lat, s_lon );
  g_free ( s_lat ); s_lat = NULL;
  g_free ( s_lon ); s_lon = NULL;

  s_alt = NULL;
  if ( tp->altitude != VIK_DEFAULT_ALTITUDE )
  {
    s_alt = a_coords_dtostr ( tp->altitude );
  }
  else if ( context->options != NULL && context->options->force_ele )
  {
    s_alt = a_coords_dtostr ( 0 );
  }
  if (s_alt != NULL)
    fprintf ( f, "    <ele>%s</ele>\n", s_alt );
  g_free ( s_alt ); s_alt = NULL;
  
  time_iso8601 = NULL;
  if ( tp->has_timestamp ) {
    GTimeVal timestamp;
    timestamp.tv_sec = tp->timestamp;
    timestamp.tv_usec = 0;
  
    time_iso8601 = g_time_val_to_iso8601 ( &timestamp );
  }
  else if ( context->options != NULL && context->options->force_time )
  {
    GTimeVal current;
    g_get_current_time ( &current );
  
    time_iso8601 = g_time_val_to_iso8601 ( &current );
  }
  if ( time_iso8601 != NULL )
    fprintf ( f, "    <time>%s</time>\n", time_iso8601 );
  g_free(time_iso8601);
  time_iso8601 = NULL;
  
  if (!isnan(tp->course)) {
    gchar *s_course = a_coords_dtostr(tp->course);
    fprintf ( f, "    <course>%s</course>\n", s_course );
    g_free(s_course);
  }
  if (!isnan(tp->speed)) {
    gchar *s_speed = a_coords_dtostr(tp->speed);
    fprintf ( f, "    <speed>%s</speed>\n", s_speed );
    g_free(s_speed);
  }
  if (tp->fix_mode == VIK_GPS_MODE_2D)
    fprintf ( f, "    <fix>2d</fix>\n");
  if (tp->fix_mode == VIK_GPS_MODE_3D)
    fprintf ( f, "    <fix>3d</fix>\n");
  if (tp->nsats > 0)
    fprintf ( f, "    <sat>%d</sat>\n", tp->nsats );

  s_dop = NULL;
  if ( tp->hdop != VIK_DEFAULT_DOP )
  {
    s_dop = a_coords_dtostr ( tp->hdop );
  }
  if (s_dop != NULL)
    fprintf ( f, "    <hdop>%s</hdop>\n", s_dop );
  g_free ( s_dop ); s_dop = NULL;

  if ( tp->vdop != VIK_DEFAULT_DOP )
  {
    s_dop = a_coords_dtostr ( tp->vdop );
  }
  if (s_dop != NULL)
    fprintf ( f, "    <vdop>%s</vdop>\n", s_dop );
  g_free ( s_dop ); s_dop = NULL;

  if ( tp->pdop != VIK_DEFAULT_DOP )
  {
    s_dop = a_coords_dtostr ( tp->pdop );
  }
  if (s_dop != NULL)
    fprintf ( f, "    <pdop>%s</pdop>\n", s_dop );
  g_free ( s_dop ); s_dop = NULL;


  fprintf ( f, "  </trkpt>\n" );
}