From e72e8052d63c238186d8f623b58c2f13fbcf7a9b Mon Sep 17 00:00:00 2001 From: Kaj-Michael Lang Date: Wed, 11 Jun 2008 18:13:41 +0300 Subject: [PATCH] Combine extra functions from old track.* and route.* --- src/route.h | 1 - src/track.c | 548 +++++++++++++++++++++++++++++++++++++++++++--------- src/track.h | 21 +- 3 files changed, 465 insertions(+), 105 deletions(-) diff --git a/src/route.h b/src/route.h index b45031c..cdb81ef 100644 --- a/src/route.h +++ b/src/route.h @@ -33,7 +33,6 @@ gboolean route_download(Path *route, gchar *to); gboolean route_clear(Path *route); void route_check_waypoint_announce(Path *route, GpsData *gps); -void route_autoroute_check(Path *route); gboolean route_auto_route_dl_idle_cb(); void route_cancel_autoroute(Path *route, gboolean temporary); diff --git a/src/track.c b/src/track.c index 49d5abc..c6e9ca2 100644 --- a/src/track.c +++ b/src/track.c @@ -15,60 +15,59 @@ #include "latlon.h" #include "path.h" -/* Add sensitivity */ -static gint sensitivity=3; +typedef struct _OriginToggleInfo OriginToggleInfo; +struct _OriginToggleInfo { + GtkWidget *rad_use_gps; + GtkWidget *rad_use_route; + GtkWidget *rad_use_text; + GtkWidget *chk_auto; + GtkWidget *txt_from; + GtkWidget *txt_to; + Path *path; +}; -void -track_clear(Path *track) +/** + * path_clear_ask: + * @path + * @msg + * + * Ask confirmation to clear given path, using msg as the question. + * + * Returns: TRUE if path was cleared. + */ +gboolean +path_clear_ask(Path *path, const gchar *msg) { GtkWidget *confirm; +gboolean res=FALSE; -confirm = hildon_note_new_confirmation(GTK_WINDOW(_window), _("Clear the track?")); +g_return_val_if_fail(path, FALSE); +confirm=hildon_note_new_confirmation(GTK_WINDOW(_window), msg); if (GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm))) { - path_clear(track); - map_force_redraw(); + path_clear(path); + res=TRUE; } gtk_widget_destroy(confirm); -} - -gdouble -track_calculate_distance_from(Point *point) -{ -Point *curr; -gdouble lat1, lon1, lat2, lon2; -gdouble sum = 0.0; - -unit2latlon(_gps->data.unitx, _gps->data.unity, lat1, lon1); - -/* Skip _track->tail because that should be _gps. */ -for (curr = _track->tail; curr > point; --curr) { - if (curr->unity) { - unit2latlon(curr->unitx, curr->unity, lat2, lon2); - sum += calculate_distance(lat1, lon1, lat2, lon2); - lat1 = lat2; - lon1 = lon2; - } -} -return sum; +return res; } void -track_show_distance_from(Point *point) +track_show_distance_from(Path *path, Point *point) { gchar buffer[80]; gdouble sum; -sum = track_calculate_distance_from(point); +sum=path_calculate_distance_from(path, point); g_snprintf(buffer, sizeof(buffer), "%s: %.02f %s", _("Distance"), sum * UNITS_CONVERT[_units], UNITS_TEXT[_units]); MACRO_BANNER_SHOW_INFO(_window, buffer); } void -track_show_distance_from_last() +track_show_distance_from_last(Path *track) { /* Find last zero point. */ -if (_track->head != _track->tail) { +if (track->head != track->tail) { Point *point; /* Find last zero point. */ for (point = _track->tail; point->unity; point--) { @@ -80,90 +79,448 @@ if (_track->head != _track->tail) { } void -track_show_distance_from_first() +track_show_distance_from_first(Path *track) { -if (_track->head != _track->tail) { - track_show_distance_from(_track->head); +if (track->head != track->tail) { + track_show_distance_from(track->head); } else { MACRO_BANNER_SHOW_INFO(_window, _("The current track is empty.")); } } /** - * Add a point to the _track list. - * - * If a non-null gps is given, then the current position is appended - * to _track with the given time. If gps is null, then _point_null is - * appended to _track with time zero (this produces a "break" in the track). + * Check if we should re-calculate route + */ +void +route_autoroute_check(Path *route) +{ +g_return_if_fail(route); + +if (_autoroute_data.enabled && !_autoroute_data.in_progress && route->near_point_dist_squared > 400) { + MACRO_BANNER_SHOW_INFO(_window, _("Recalculating directions...")); + _autoroute_data.in_progress = TRUE; + show_directions = FALSE; + g_idle_add((GSourceFunc)route_auto_route_dl_idle_cb, NULL); +} +} + +gboolean +route_open_file(Path *route) +{ +gchar *buffer; +gint size; + +g_return_val_if_fail(route, FALSE); + +if (file_open_get_contents(&_route_dir_uri, &buffer, &size)) { + /* If auto is enabled, append the route, otherwise replace it. */ + if (path_gpx_parse(route, buffer, size, _autoroute_data.enabled ? GPX_PATH_APPEND : GPX_PATH_NEW)) { + route_cancel_autoroute(route, FALSE); + + MACRO_BANNER_SHOW_INFO(_window, _("Route Opened")); + /* Find the nearest route point, if we're connected. */ + path_find_nearest_point(route); + route_set_destination_from_last(route, &_dest); + return TRUE; + } else { + popup_error(_window, _("Error parsing GPX file.")); + g_free(buffer); + return FALSE; + } +} +return FALSE; +} + +/** + * Ask user to save route */ gboolean -track_add(Path *track, GpsData *gps) +route_save(Path *route) { -if (!gps) { - MACRO_PATH_INCREMENT_TAIL(*track); - *track->tail=_point_null; +GnomeVFSHandle *handle; + +g_return_val_if_fail(route, FALSE); + +if (route->head==route->tail) { + MACRO_BANNER_SHOW_INFO(_window, _("No route exist.")); return FALSE; } -g_assert(track); -if (abs((gint)gps->unitx-track->tail->unitx) > sensitivity || abs((gint)gps->unity-track->tail->unity) > sensitivity) { - - /* If gps is available, update the nearest-waypoint data. */ - /* XXX: MOVE THIS */ - if (gps && _route->head != _route->tail && (gps->newly_fixed ? (route_find_nearest_point(_route), TRUE) : route_update_nears(_route, TRUE))) { - /* Nearest waypoint has changed - re-render paths. */ - map_render_paths(); - MACRO_QUEUE_DRAW_AREA(); +if (file_save(&_route_dir_uri, &_route_dir_uri, &handle)) { + if (path_gpx_write(route, handle)) { + MACRO_BANNER_SHOW_INFO(_window, _("Route Saved")); + } else { + popup_error(_window, _("Error writing GPX file.")); } + gnome_vfs_close(handle); + return TRUE; +} +return FALSE; +} - if (_show_tracks & TRACKS_MASK) { - gint tx1, ty1, tx2, ty2; - - /* Instead of calling map_render_paths(), we'll draw the new line - * ourselves and call gtk_widget_queue_draw_area(). */ - map_render_segment(_gc[COLORABLE_TRACK], _gc[COLORABLE_TRACK_BREAK], - track->tail->unitx, track->tail->unity, gps->unitx, gps->unity); - - if (track->tail->unity && track->tail->unitx) { - tx1 = unit2x(track->tail->unitx); - ty1 = unit2y(track->tail->unity); - tx2 = unit2x(gps->unitx); - ty2 = unit2y(gps->unity); - - /* XXX: This should not be here... */ - gtk_widget_queue_draw_area(_map_widget, - MIN(tx1, tx2) - _draw_width, - MIN(ty1, ty2) - _draw_width, - abs(tx1 - tx2) + (2 * _draw_width), - abs(ty1 - ty2) + (2 * _draw_width)); +/** + * + */ +static gboolean +route_origin_type_selected_cb(GtkWidget *toggle, OriginToggleInfo *oti) +{ +if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle))) { + if (toggle == oti->rad_use_gps) { + gchar buffer[80]; + gchar strlat[32]; + gchar strlon[32]; + g_ascii_formatd(strlat, 32, "%.06f", _gps->data.lat); + g_ascii_formatd(strlon, 32, "%.06f", _gps->data.lon); + g_snprintf(buffer, sizeof(buffer), "%s, %s", strlat, strlon); + gtk_entry_set_text(GTK_ENTRY(oti->txt_from), buffer); + } else if (toggle == oti->rad_use_route) { + gchar buffer[80]; + gchar strlat[32]; + gchar strlon[32]; + gdouble lat, lon; + Point *p; + + p=path_find_last_point(oti->path); + if (p) { + unit2latlon(p->unitx, p->unity, &lat, &lon); + g_ascii_formatd(strlat, 32, "%.06f", lat); + g_ascii_formatd(strlon, 32, "%.06f", lon); + g_snprintf(buffer, sizeof(buffer), "%s, %s", strlat, strlon); + gtk_entry_set_text(GTK_ENTRY(oti->txt_from), buffer); } } + gtk_widget_set_sensitive(oti->txt_from, toggle == oti->rad_use_text); + gtk_widget_set_sensitive(oti->chk_auto, toggle == oti->rad_use_gps); +} +return TRUE; +} - if (track->tail->unity && track->tail->unitx) { - gdouble lat, lon; +/** + * Cancel the current auto-route. + */ +void +route_cancel_autoroute(Path *route, gboolean temporary) +{ +if (_autoroute_data.enabled) { + if (!temporary) { + _autoroute_data.enabled = FALSE; + + g_free(_autoroute_data.dest); + _autoroute_data.dest = NULL; - unit2latlon(track->tail->unitx, track->tail->unity, lat, lon); - track->length += calculate_distance(lat, lon, gps->lat, gps->lon); - track->tspeed+=gps->speed; - if (track->points>0) - track->avgspeed=track->tspeed/track->points; - else - track->avgspeed=0.0; - g_debug("TRACK: %f %f (%d)", track->length, track->avgspeed, track->points); + g_free(_autoroute_data.src_str); + _autoroute_data.src_str = NULL; } - MACRO_PATH_INCREMENT_TAIL(*track); - track->tail->unitx=gps->unitx; - track->tail->unity=gps->unity; - track->tail->time=gps->time; - track->tail->altitude=gps->altitude; - track->maxspeed=gps->maxspeed; - track->points++; + if (_autoroute_data.curl_easy) { + if (_curl_multi) + curl_multi_remove_handle(_curl_multi, _autoroute_data.curl_easy); + curl_easy_cleanup(_autoroute_data.curl_easy); + _autoroute_data.curl_easy = NULL; + } + + g_free(_autoroute_data.rdl_data.bytes); + _autoroute_data.rdl_data.bytes = NULL; + _autoroute_data.rdl_data.bytes_read = 0; + + _autoroute_data.in_progress = FALSE; +} +} + +/** + * Read the data provided by the given handle as GPX data, updating the + * auto-route with that data. + */ +size_t +route_dl_cb_read(void *ptr, size_t size, size_t nmemb, RouteDownloadData * rdl_data) +{ +size_t old_size = rdl_data->bytes_read; + +rdl_data->bytes_read += size * nmemb; +rdl_data->bytes = g_renew(gchar, rdl_data->bytes, rdl_data->bytes_read); +g_memmove(rdl_data->bytes + old_size, ptr, size * nmemb); + +return (size * nmemb); } +gboolean +route_auto_route_dl_idle_cb() +{ +gchar latstr[32], lonstr[32], *latlonstr; + +g_ascii_dtostr(latstr, 32, _gps->data.lat); +g_ascii_dtostr(lonstr, 32, _gps->data.lon); +latlonstr = g_strdup_printf("%s,%s", latstr, lonstr); +_autoroute_data.src_str = g_strdup_printf(_route_dl_url, latlonstr, _autoroute_data.dest); +g_free(latlonstr); + +MACRO_CURL_EASY_INIT(_autoroute_data.curl_easy); +curl_easy_setopt(_autoroute_data.curl_easy, CURLOPT_URL, _autoroute_data.src_str); +curl_easy_setopt(_autoroute_data.curl_easy, CURLOPT_WRITEFUNCTION, route_dl_cb_read); +curl_easy_setopt(_autoroute_data.curl_easy, CURLOPT_WRITEDATA, &_autoroute_data.rdl_data); +curl_multi_add_handle(_curl_multi, _autoroute_data.curl_easy); + +if (iap_is_connected() && !_curl_sid) + _curl_sid = g_timeout_add(100, (GSourceFunc)map_download_timeout, NULL); + +_autoroute_data.in_progress = TRUE; + +return FALSE; +} + +/** + * Display a dialog box to the user asking them to download a route. The + * "From" and "To" textfields may be initialized using the first two + * parameters. The third parameter, if set to TRUE, will cause the "Use GPS + * Location" checkbox to be enabled, which automatically sets the "From" to the + * current GPS position (this overrides any value that may have been passed as + * the "To" initializer). + * None of the passed strings are freed - that is left to the caller, and it is + * safe to free either string as soon as this function returns. + */ +gboolean +route_download(Path *route, gchar *to) +{ +GtkWidget *dialog; +GtkWidget *table; +GtkWidget *label; +GtkWidget *txt_source_url; +GtkWidget *hbox; +OriginToggleInfo oti; +GtkEntryCompletion *from_comp; +GtkEntryCompletion *to_comp; +gboolean r=FALSE; + +oti.path=route; + +dialog = gtk_dialog_new_with_buttons(_("Download Route"), + GTK_WINDOW(_window), + GTK_DIALOG_MODAL, GTK_STOCK_OK, + GTK_RESPONSE_ACCEPT, + GTK_STOCK_CANCEL, + GTK_RESPONSE_REJECT, NULL); + +help_dialog_help_enable(GTK_DIALOG(dialog), HELP_ID_DOWNROUTE); +gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), table = gtk_table_new(2, 5, FALSE), TRUE, TRUE, 0); + +from_comp = gtk_entry_completion_new(); +gtk_entry_completion_set_model(from_comp, GTK_TREE_MODEL(_loc_model)); +gtk_entry_completion_set_text_column(from_comp, 0); +to_comp = gtk_entry_completion_new(); +gtk_entry_completion_set_model(to_comp, GTK_TREE_MODEL(_loc_model)); +gtk_entry_completion_set_text_column(to_comp, 0); + +/* Source URL. */ +gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(_("Source URL")), 0, 1, 0, 1, GTK_FILL, 0, 2, 4); +gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); +gtk_table_attach(GTK_TABLE(table), txt_source_url = gtk_entry_new(), 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, 0, 2, 4); +gtk_entry_set_width_chars(GTK_ENTRY(txt_source_url), 25); + +/* Auto. */ +gtk_table_attach(GTK_TABLE(table), hbox = gtk_hbox_new(FALSE, 6), 0, 2, 1, 2, GTK_FILL, 0, 2, 4); +gtk_box_pack_start(GTK_BOX(hbox), oti.rad_use_gps = gtk_radio_button_new_with_label(NULL, _("Use GPS Location")), TRUE, TRUE, 0); +gtk_box_pack_start(GTK_BOX(hbox), oti.chk_auto = gtk_check_button_new_with_label(_("Auto-Update")), TRUE, TRUE, 0); +gtk_widget_set_sensitive(oti.chk_auto, FALSE); + +/* Use End of Route. */ +gtk_table_attach(GTK_TABLE(table), hbox = gtk_hbox_new(FALSE, 6), 0, 2, 2, 3, GTK_FILL, 0, 2, 4); +gtk_box_pack_start(GTK_BOX(hbox), oti.rad_use_route = gtk_radio_button_new_with_label_from_widget + (GTK_RADIO_BUTTON(oti.rad_use_gps), _("Use End of Route")), TRUE, TRUE, 0); +gtk_widget_set_sensitive(oti.rad_use_route, route->head != route->tail); + +/* Origin. */ +gtk_table_attach(GTK_TABLE(table), oti.rad_use_text = gtk_radio_button_new_with_label_from_widget + (GTK_RADIO_BUTTON(oti.rad_use_gps), _("Origin")), 0, 1, 3, 4, GTK_FILL, 0, 2, 4); +gtk_table_attach(GTK_TABLE(table), oti.txt_from = gtk_entry_new(), 1, 2, 3, 4, GTK_EXPAND | GTK_FILL, 0, 2, 4); +gtk_entry_set_completion(GTK_ENTRY(oti.txt_from), from_comp); +gtk_entry_set_width_chars(GTK_ENTRY(oti.txt_from), 25); + +/* Destination. */ +gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(_("Destination")), 0, 1, 4, 5, GTK_FILL, 0, 2, 4); +gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); +gtk_table_attach(GTK_TABLE(table), oti.txt_to = gtk_entry_new(), 1, 2, 4, 5, GTK_EXPAND | GTK_FILL, 0, 2, 4); +gtk_entry_set_completion(GTK_ENTRY(oti.txt_to), to_comp); +gtk_entry_set_width_chars(GTK_ENTRY(oti.txt_to), 25); + +g_signal_connect(G_OBJECT(oti.rad_use_gps), "toggled", G_CALLBACK(route_origin_type_selected_cb), &oti); +g_signal_connect(G_OBJECT(oti.rad_use_route), "toggled", G_CALLBACK(route_origin_type_selected_cb), &oti); +g_signal_connect(G_OBJECT(oti.rad_use_text), "toggled", G_CALLBACK(route_origin_type_selected_cb), &oti); + +#if defined (WITH_HILDON) && defined (HILDON_AUTOCAP) +g_object_set(G_OBJECT(oti.txt_from), HILDON_AUTOCAP, FALSE, NULL); +g_object_set(G_OBJECT(oti.txt_to), HILDON_AUTOCAP, FALSE, NULL); +#endif + +/* Initialize fields. */ +gtk_entry_set_text(GTK_ENTRY(txt_source_url), _route_dl_url); +gtk_entry_set_text(GTK_ENTRY(oti.txt_to), (to ? to : "")); + +gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(oti.rad_use_text), TRUE); + +if (route->head != route->tail) { + /* Use "End of Route" by default if they have a route. */ + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(oti.rad_use_route), TRUE); + gtk_widget_grab_focus(oti.rad_use_route); +} else if (_enable_gps) { + /* Else use "GPS Location" if they have GPS enabled. */ + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(oti.rad_use_gps), TRUE); + gtk_widget_grab_focus(oti.rad_use_gps); +} else { + /* Else use text. */ + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(oti.rad_use_text), TRUE); + gtk_widget_grab_focus(oti.txt_from); +} + +gtk_widget_show_all(dialog); + +while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) { + CURL *curl_easy; + RouteDownloadData rdl_data = { 0, 0 }; + gchar buffer[BUFFER_SIZE]; + const gchar *source_url, *from, *to; + gchar *from_escaped, *to_escaped; + + source_url = gtk_entry_get_text(GTK_ENTRY(txt_source_url)); + if (!strlen(source_url)) { + popup_error(dialog, _("Please specify a source URL.")); + continue; + } else { + g_free(_route_dl_url); + _route_dl_url = g_strdup(source_url); + } + + from = gtk_entry_get_text(GTK_ENTRY(oti.txt_from)); + if (!strlen(from)) { + popup_error(dialog, _("Please specify a start location.")); + continue; + } + + to = gtk_entry_get_text(GTK_ENTRY(oti.txt_to)); + if (!strlen(to)) { + popup_error(dialog, _("Please specify an end location.")); + continue; + } + + from_escaped = gnome_vfs_escape_string(from); + to_escaped = gnome_vfs_escape_string(to); + g_snprintf(buffer, sizeof(buffer), source_url, from_escaped, to_escaped); + g_free(from_escaped); + g_free(to_escaped); + + iap_connect(); + + /* Attempt to download the route from the server. */ + MACRO_CURL_EASY_INIT(curl_easy); + curl_easy_setopt(curl_easy, CURLOPT_URL, buffer); + curl_easy_setopt(curl_easy, CURLOPT_WRITEFUNCTION, route_dl_cb_read); + curl_easy_setopt(curl_easy, CURLOPT_WRITEDATA, &rdl_data); + if (CURLE_OK != curl_easy_perform(curl_easy)) { + popup_error(dialog, _("Failed to connect to GPX Directions server")); + curl_easy_cleanup(curl_easy); + g_free(rdl_data.bytes); + /* Let them try again */ + continue; + } + curl_easy_cleanup(curl_easy); + + if (strncmp(rdl_data.bytes, "unitx, point->unity, &lat, &lon); +sum=path_get_distance_to(route, point, lat, lon); +g_snprintf(buffer, sizeof(buffer), "%s: %.02f %s", _("Distance"), sum * UNITS_CONVERT[_units], UNITS_TEXT[_units]); +MACRO_BANNER_SHOW_INFO(_window, buffer); + return TRUE; } +void +route_show_distance_to_next_waypoint(Path *route) +{ +g_return_if_fail(route); + +if (!route_show_distance_to(route, NULL)) + MACRO_BANNER_SHOW_INFO(_window, _("There is no next waypoint.")); +} + +void +route_show_distance_to_last(Path *route) +{ +g_return_if_fail(route); + +if (route->head != route->tail) { + route_show_distance_to(route, path_find_last_point(route)); +} else { + MACRO_BANNER_SHOW_INFO(_window, _("The current route is empty.")); +} +} + gboolean track_open(Path *track) { @@ -172,8 +529,7 @@ gint size; gboolean r = FALSE; if (file_open_get_contents(&_track_file_uri, &buffer, &size)) { - if (gpx_parse(track, buffer, size, GPX_PATH_NEW)) { - map_force_redraw(); + if (path_gpx_parse(track, buffer, size, GPX_PATH_NEW)) { MACRO_BANNER_SHOW_INFO(_window, _("Track Opened")); r = TRUE; } else { @@ -191,10 +547,10 @@ GnomeVFSHandle *handle; gboolean r = FALSE; if (file_save(&_track_file_uri, &_track_file_uri, &handle)) { - if (gpx_write(track, handle)) { + if (path_gpx_write(track, handle)) { MACRO_BANNER_SHOW_INFO(_window, _("Track Saved")); r = TRUE; - track_clear(track); + path_clear_ask(track); } else { popup_error(_window, _("Error writing GPX file.")); } @@ -227,10 +583,10 @@ dialog = gtk_dialog_new_with_buttons(_("Insert Mark"), gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), table = gtk_table_new(2, 2, FALSE), TRUE, TRUE, 0); -gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(_("Lat, Lon")), 0, 1, 0, 1, GTK_FILL, 0, 2, 4); +gtk_table_attach(GTK_TABLE(table), label = gtk_label_new(_("Near Lat, Lon")), 0, 1, 0, 1, GTK_FILL, 0, 2, 4); gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f); -unit2latlon(_gps->data.unitx, _gps->data.unity, lat, lon); +unit2latlon(_gps->data.unitx, _gps->data.unity, &lat, &lon); lat_format(_degformat, lat, tmp1); lon_format(_degformat, lon, tmp2); p_latlon = g_strdup_printf("%s, %s", tmp1, tmp2); diff --git a/src/track.h b/src/track.h index 352504a..a19760b 100644 --- a/src/track.h +++ b/src/track.h @@ -8,16 +8,21 @@ Path *_track; -#define TRACK_SQL_SELECT_TRACKS "select id,name,slat,slon,elat,elon,len,sdate,edate from tracks order by sdate" -#define TRACK_SQL_INSERT_TRACK "insert into tracks (id,name,sloc,sdate) values (?,?,?,?); -#define TRACK_SQL_INSERT_TRACK_POINT "insert into trackpoints (tid,dt,lat,lon,alt,hdop,vdop,pdop,sat,fix) values (?,?,?,?,?,?,?,?,?,?)" -#define TRACK_SQL_SELECT_TRACK_POINTS "select tid,dt,lat,lon,alt,hdop,vdop,pdop,sat,fix from trackpoints where tid=? order by dt" -void track_init(void); -void track_deinit(void); +/** The singleton auto-route-download data. */ +AutoRouteDownloadData _autoroute_data; + +gboolean route_open_file(Path *route); +gboolean route_save(Path *route); +gboolean route_download(Path *route, gchar *to); +gboolean route_clear(Path *route); + +void route_autoroute_check(Path *route); +gboolean route_show_distance_to(Path *route, Point *point); +void route_show_distance_to_last(Path *route); +void route_show_distance_to_next(Path *route); + -gboolean track_add(Path *track, GpsData *gps); -gboolean track_insert_mark(Path *track); gboolean track_save(Path *track); gboolean track_open(Path *track); void track_clear(Path *track); -- 2.39.5