]> err.no Git - mapper/blob - src/track.c
Use new speak function
[mapper] / src / track.c
1 #include <config.h>
2
3 #include "utils.h"
4 #include "gps.h"
5 #include "map.h"
6 #include "route.h"
7 #include "settings.h"
8 #include "mapper-types.h"
9 #include "ui-common.h"
10 #include "file.h"
11
12 #include "track.h"
13
14 void path_resize(Path * path, guint size)
15 {
16         printf("%s()\n", __PRETTY_FUNCTION__);
17
18         if (path->head + size != path->cap) {
19                 Point *old_head = path->head;
20                 WayPoint *curr;
21                 path->head = g_renew(Point, old_head, size);
22                 path->cap = path->head + size;
23                 if (path->head != old_head) {
24                         path->tail = path->head + (path->tail - old_head);
25
26                         /* Adjust all of the waypoints. */
27                         for (curr = path->whead - 1; curr++ != path->wtail;)
28                                 curr->point =
29                                     path->head + (curr->point - old_head);
30                 }
31         }
32
33         vprintf("%s(): return\n", __PRETTY_FUNCTION__);
34 }
35
36 void path_wresize(Path * path, guint wsize)
37 {
38         printf("%s()\n", __PRETTY_FUNCTION__);
39
40         if (path->whead + wsize != path->wcap) {
41                 WayPoint *old_whead = path->whead;
42                 path->whead = g_renew(WayPoint, old_whead, wsize);
43                 path->wtail = path->whead + (path->wtail - old_whead);
44                 path->wcap = path->whead + wsize;
45         }
46
47         vprintf("%s(): return\n", __PRETTY_FUNCTION__);
48 }
49
50 void track_clear()
51 {
52         GtkWidget *confirm;
53
54         confirm = hildon_note_new_confirmation(GTK_WINDOW(_window),
55                                                _("Really clear the track?"));
56
57         if (GTK_RESPONSE_OK == gtk_dialog_run(GTK_DIALOG(confirm))) {
58                 _track.tail = _track.head;
59                 map_force_redraw();
60         }
61
62         gtk_widget_destroy(confirm);
63 }
64
65 gfloat track_calculate_distance_from(Point * point)
66 {
67         gfloat lat1, lon1, lat2, lon2;
68         gfloat sum = 0.0;
69         Point *curr;
70         unit2latlon(_pos.unitx, _pos.unity, lat1, lon1);
71
72         /* Skip _track.tail because that should be _pos. */
73         for (curr = _track.tail; curr > point; --curr) {
74                 if (curr->unity) {
75                         unit2latlon(curr->unitx, curr->unity, lat2, lon2);
76                         g_printf("B:[%f %f %f %f (%f)]\n", lat1, lon1, lat2,
77                                  lon2, sum);
78                         sum += calculate_distance(lat1, lon1, lat2, lon2);
79                         lat1 = lat2;
80                         lon1 = lon2;
81                 }
82         }
83         return sum;
84 }
85
86 void track_show_distance_from(Point * point)
87 {
88         gchar buffer[80];
89         gfloat sum;
90
91         sum = track_calculate_distance_from(point);
92
93         snprintf(buffer, sizeof(buffer), "%s: %.02f %s", _("Distance"),
94                  sum * UNITS_CONVERT[_units], UNITS_TEXT[_units]);
95         MACRO_BANNER_SHOW_INFO(_window, buffer);
96 }
97
98 void track_show_distance_from_last()
99 {
100         printf("%s()\n", __PRETTY_FUNCTION__);
101
102         /* Find last zero point. */
103         if (_track.head != _track.tail) {
104                 Point *point;
105                 /* Find last zero point. */
106                 for (point = _track.tail; point->unity; point--) {
107                 }
108                 track_show_distance_from(point);
109         } else {
110                 MACRO_BANNER_SHOW_INFO(_window,
111                                        _("The current track is empty."));
112         }
113         printf("%s(): return\n", __PRETTY_FUNCTION__);
114 }
115
116 void track_show_distance_from_first()
117 {
118         printf("%s()\n", __PRETTY_FUNCTION__);
119
120         /* Find last zero point. */
121         if (_track.head != _track.tail) {
122                 track_show_distance_from(_track.head);
123         } else {
124                 MACRO_BANNER_SHOW_INFO(_window,
125                                        _("The current track is empty."));
126         }
127         printf("%s(): return\n", __PRETTY_FUNCTION__);
128 }
129
130 /**
131  * Add a point to the _track list.  This function is slightly overloaded,
132  * since it is what houses the check for "have we moved
133  * significantly": it also initiates the re-calculation of the _near_point
134  * data, as well as calling osso_display_state_on() when we have the focus.
135  *
136  * If a non-zero time is given, then the current position (as taken from the
137  * _pos variable) is appended to _track with the given time.  If time is zero,
138  * then _point_null is appended to _track with time zero (this produces a "break"
139  * in the track).
140  */
141 void track_add(time_t time, gboolean newly_fixed)
142 {
143         gboolean show_directions = TRUE;
144         gint announce_thres_unsquared;
145         printf("%s(%u, %u)\n", __PRETTY_FUNCTION__, _pos.unitx, _pos.unity);
146
147         if (abs((gint) _pos.unitx - _track.tail->unitx) > _draw_width
148             || abs((gint) _pos.unity - _track.tail->unity) > _draw_width) {
149
150                 /* If time != 0, update the nearest-waypoint data. */
151                 if (time && _route.head != _route.tail && 
152                         (newly_fixed ? (route_find_nearest_point(), TRUE) : route_update_nears(TRUE))) {
153                         /* Nearest waypoint has changed - re-render paths. */
154                         map_render_paths();
155                         MACRO_QUEUE_DRAW_AREA();
156                 }
157
158                 if (_show_tracks & TRACKS_MASK) {
159                         gint tx1, ty1, tx2, ty2;
160
161                         /* Instead of calling map_render_paths(), we'll draw the new line
162                          * ourselves and call gtk_widget_queue_draw_area(). */
163                         map_render_segment(_gc[COLORABLE_TRACK],
164                                            _gc[COLORABLE_TRACK_BREAK],
165                                            _track.tail->unitx,
166                                            _track.tail->unity, _pos.unitx,
167                                            _pos.unity);
168
169                         if (time && _track.tail->unity) {
170                                 tx1 = unit2x(_track.tail->unitx);
171                                 ty1 = unit2y(_track.tail->unity);
172                                 tx2 = unit2x(_pos.unitx);
173                                 ty2 = unit2y(_pos.unity);
174                                 gtk_widget_queue_draw_area(_map_widget,
175                                                            MIN(tx1, tx2) - _draw_width, 
176                                                            MIN(ty1, ty2) - _draw_width,
177                                                            abs(tx1 - tx2) + (2 * _draw_width),
178                                                            abs(ty1 - ty2) + (2 * _draw_width));
179                         }
180                 }
181
182                 MACRO_PATH_INCREMENT_TAIL(_track);
183
184                 if (time)
185                         *_track.tail = _pos;
186                 else
187                         *_track.tail = _point_null;
188
189                 if (_autoroute_data.enabled && !_autoroute_data.in_progress && _near_point_dist_squared > 400) {
190                         MACRO_BANNER_SHOW_INFO(_window, _("Recalculating directions..."));
191                         _autoroute_data.in_progress = TRUE;
192                         show_directions = FALSE;
193                         g_idle_add((GSourceFunc) auto_route_dl_idle, NULL);
194                 }
195
196                 /* Keep the display on. */
197                 KEEP_DISPLAY_ON();
198         }
199
200         announce_thres_unsquared = (20 + (guint) _gps.speed) * _announce_notice_ratio * 3;
201
202         /* Check if we should announce upcoming waypoints. */
203         if (show_directions && time && _next_way_dist_squared
204             < (announce_thres_unsquared * announce_thres_unsquared)) {
205                 if (_enable_voice && strcmp(_next_way->desc, _last_spoken_phrase)) {
206                         g_free(_last_spoken_phrase);
207                         _last_spoken_phrase = g_strdup(_next_way->desc);
208                         speak_text(_last_spoken_phrase);
209                 }
210                 MACRO_BANNER_SHOW_INFO(_window, _next_way->desc);
211         }
212
213         vprintf("%s(): return\n", __PRETTY_FUNCTION__);
214 }
215
216 void track_insert_break(void)
217 {
218         printf("%s()\n", __PRETTY_FUNCTION__);
219
220         if (_track.tail->unity) {
221                 guint x1, y1;
222
223                 /* To mark a "waypoint" in a track, we'll add a (0, 0) point and then
224                  * another instance of the most recent track point. */
225                 MACRO_PATH_INCREMENT_TAIL(_track);
226                 *_track.tail = _point_null;
227                 MACRO_PATH_INCREMENT_TAIL(_track);
228                 *_track.tail = _track.tail[-2];
229
230         /** Instead of calling map_render_paths(), we'll just add the waypoint
231          * ourselves. */
232                 x1 = unit2bufx(_track.tail->unitx);
233                 y1 = unit2bufy(_track.tail->unity);
234                 /* Make sure this circle will be visible. */
235                 if ((x1 < BUF_WIDTH_PIXELS) && ((unsigned)y1 < BUF_HEIGHT_PIXELS))
236                         gdk_draw_arc(_map_pixmap, _gc[COLORABLE_TRACK_BREAK], FALSE,    /* FALSE: not filled. */
237                                      x1 - _draw_width, y1 - _draw_width, 2 * _draw_width, 2 * _draw_width, 0,   /* start at 0 degrees. */
238                                      360 * 64);
239         } else {
240                 MACRO_BANNER_SHOW_INFO(_window, _("Break already inserted."));
241         }
242
243         vprintf("%s(): return\n", __PRETTY_FUNCTION__);
244 }
245
246 gboolean track_open(void)
247 {
248         gchar *buffer;
249         gint size;
250         gboolean r = FALSE;
251
252         if (open_file(&buffer, NULL, &size, NULL, &_track_file_uri, GTK_FILE_CHOOSER_ACTION_OPEN)) {
253                 if (parse_gpx(&_track, buffer, size, -1)) {
254                         map_force_redraw();
255                         MACRO_BANNER_SHOW_INFO(_window, _("Track Opened"));
256                         r = TRUE;
257                 } else {
258                         popup_error(_window, _("Error parsing GPX file."));
259                 }
260                 g_free(buffer);
261         }
262         return r;
263 }
264
265 gboolean track_save(void)
266 {
267         GnomeVFSHandle *handle;
268         gboolean r = FALSE;
269
270         if (file_save(&_track_file_uri, &_track_file_uri, &handle)) {
271                 if (write_gpx(&_track, handle)) {
272                         MACRO_BANNER_SHOW_INFO(_window, _("Track Saved"));
273                         r = TRUE;
274                 } else {
275                         popup_error(_window, _("Error writing GPX file."));
276                 }
277                 gnome_vfs_close(handle);
278         }
279         return r;
280 }
281
282 /**
283  * Add a text description at current point
284  * 
285  */
286 void track_insert_mark_text(gchar *text)
287 {
288 MACRO_PATH_INCREMENT_WTAIL(_track);
289 _track.wtail->point = _track.tail;
290 _track.wtail->desc = text;
291 }
292
293 /**
294  * Ask for a text description for the current point
295  *
296  */
297
298 gboolean track_insert_mark(void)
299 {
300 gfloat lat, lon;
301 gchar tmp1[16], tmp2[16], *p_latlon;
302 GtkWidget *dialog;
303 GtkWidget *table;
304 GtkWidget *label;
305 GtkWidget *txt_scroll;
306 GtkWidget *txt_desc;
307
308 printf("%s()\n", __PRETTY_FUNCTION__);
309
310 dialog = gtk_dialog_new_with_buttons(_("Insert Mark"),
311                                      GTK_WINDOW(_window),
312                                      GTK_DIALOG_MODAL, GTK_STOCK_OK,
313                                      GTK_RESPONSE_ACCEPT,
314                                      GTK_STOCK_CANCEL,
315                                      GTK_RESPONSE_REJECT, NULL);
316
317 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox),
318                    table = gtk_table_new(2, 2, FALSE), TRUE, TRUE, 0);
319
320 gtk_table_attach(GTK_TABLE(table),
321                  label = gtk_label_new(_("Lat, Lon")),
322                  0, 1, 0, 1, GTK_FILL, 0, 2, 4);
323 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
324
325 unit2latlon(_pos.unitx, _pos.unity, lat, lon);
326 lat_format(lat, tmp1);
327 lon_format(lon, tmp2);
328 p_latlon = g_strdup_printf("%s, %s", tmp1, tmp2);
329 gtk_table_attach(GTK_TABLE(table),
330                  label = gtk_label_new(p_latlon),
331                  1, 2, 0, 1, GTK_FILL, 0, 2, 4);
332 gtk_misc_set_alignment(GTK_MISC(label), 0.0f, 0.5f);
333 g_free(p_latlon);
334
335 gtk_table_attach(GTK_TABLE(table),
336                  label = gtk_label_new(_("Description")),
337                  0, 1, 1, 2, GTK_FILL, 0, 2, 4);
338 gtk_misc_set_alignment(GTK_MISC(label), 1.f, 0.5f);
339
340 txt_scroll = gtk_scrolled_window_new(NULL, NULL);
341 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(txt_scroll),
342                                             GTK_SHADOW_IN);
343 gtk_table_attach(GTK_TABLE(table),
344                  txt_scroll,
345                  1, 2, 1, 2, GTK_EXPAND | GTK_FILL, 0, 2, 4);
346
347 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(txt_scroll),
348                                GTK_POLICY_AUTOMATIC,
349                                GTK_POLICY_AUTOMATIC);
350
351 txt_desc = gtk_text_view_new();
352 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(txt_desc), GTK_WRAP_WORD);
353
354 gtk_container_add(GTK_CONTAINER(txt_scroll), txt_desc);
355 gtk_widget_set_size_request(GTK_WIDGET(txt_scroll), 450, 80);
356
357 gtk_widget_show_all(dialog);
358
359 while (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(dialog))) {
360         GtkTextBuffer *tbuf;
361         GtkTextIter ti1, ti2;
362
363         tbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(txt_desc));
364         gtk_text_buffer_get_iter_at_offset(tbuf, &ti1, 0);
365         gtk_text_buffer_get_end_iter(tbuf, &ti2);
366
367         if (gtk_text_buffer_get_char_count(tbuf)>0) {
368                 track_insert_mark_text(gtk_text_buffer_get_text(tbuf, &ti1, &ti2, TRUE));
369         } else {
370                 popup_error(dialog, _("Please provide a description for the mark."));
371                 continue;
372         }
373
374         map_render_paths();
375         MACRO_QUEUE_DRAW_AREA();
376         break;
377 }
378 gtk_widget_destroy(dialog);
379 }