You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

stmwpp.cc 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /*
  2. Support for "Suunto Trek Manager" (STM) WaypointPlus files,
  3. see homepage "http://www.suunto.fi" for more details,
  4. Copyright (C) 2005,2007 Olaf Klein, o.b.klein@gpsbabel.org
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
  16. */
  17. #include "defs.h"
  18. #if CSVFMTS_ENABLED
  19. #include "csv_util.h"
  20. #include "cet_util.h"
  21. #include <ctype.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. static gbfile* fin, *fout;
  25. static route_head* track, *route;
  26. static Waypoint* wpt;
  27. static short_handle short_h;
  28. #define MYNAME "STMwpp"
  29. #define STM_NOTHING 0
  30. #define STM_WAYPT 1
  31. #define STM_TRKPT 2
  32. #define STM_RTEPT 3
  33. static int track_index;
  34. static int track_num;
  35. static int what;
  36. static char* index_opt = NULL;
  37. static
  38. arglist_t stmwpp_args[] = {
  39. {
  40. "index", &index_opt, "Index of route/track to write (if more than one in source)",
  41. NULL, ARGTYPE_INT, "1", NULL
  42. },
  43. ARG_TERMINATOR
  44. };
  45. static void
  46. stmwpp_rd_init(const QString& fname)
  47. {
  48. fin = gbfopen(fname, "rb", MYNAME);
  49. track = NULL;
  50. route = NULL;
  51. wpt = NULL;
  52. }
  53. static void
  54. stmwpp_rd_deinit(void)
  55. {
  56. gbfclose(fin);
  57. }
  58. static void
  59. stmwpp_data_read(void)
  60. {
  61. char* buff;
  62. int line = 0;
  63. what = STM_NOTHING;
  64. buff = gbfgetstr(fin);
  65. buff = (buff == NULL) ? (char*) "" : buff;
  66. if (case_ignore_strncmp(buff, "Datum,WGS 84,WGS 84,", 20) != 0) {
  67. fatal(MYNAME ": Invalid GPS datum or not \"WaypointPlus\"\" file!\n");
  68. }
  69. while ((buff = gbfgetstr(fin))) {
  70. char* c;
  71. int column = -1;
  72. struct tm time;
  73. if ((line++ == 0) && fin->unicode) {
  74. cet_convert_init(CET_CHARSET_UTF8, 1);
  75. }
  76. buff = lrtrim(buff);
  77. if (*buff == '\0') {
  78. continue;
  79. }
  80. wpt = NULL;
  81. memset(&time, 0, sizeof(time));
  82. int milliseconds = 0;
  83. while ((c = csv_lineparse(buff, ",", "", column++))) {
  84. int new_what;
  85. buff = NULL;
  86. switch (column) {
  87. case 0:
  88. if (case_ignore_strcmp(c, "WP") == 0) {
  89. new_what = STM_WAYPT;
  90. } else if (case_ignore_strcmp(c, "TP") == 0) {
  91. new_what = STM_TRKPT;
  92. } else {
  93. fatal(MYNAME ": Unknown feature \"%s\"!\n", c);
  94. }
  95. if ((what != STM_NOTHING) && (new_what != what)) {
  96. fatal(MYNAME ": Only one feature (route or track) is supported by STM!\n");
  97. }
  98. what = new_what;
  99. wpt = new Waypoint;
  100. break;
  101. case 1:
  102. if (what == STM_TRKPT) {
  103. column++; /* no name -> skip column two */
  104. }
  105. break;
  106. case 2:
  107. wpt->shortname = QString::fromLatin1(c);
  108. break;
  109. case 3:
  110. wpt->latitude = atof(c);
  111. break;
  112. case 4:
  113. wpt->longitude = atof(c);
  114. break;
  115. case 5:
  116. sscanf(c, "%d/%d/%d", &time.tm_mon, &time.tm_mday, &time.tm_year);
  117. break;
  118. case 6:
  119. sscanf(c, "%d:%d:%d.%d", &time.tm_hour, &time.tm_min, &time.tm_sec, &milliseconds);
  120. /* makes sense only for recorded trackpoints */
  121. if (what != STM_TRKPT) {
  122. milliseconds = 0;
  123. }
  124. break;
  125. default:
  126. break;
  127. }
  128. }
  129. if (wpt != NULL) {
  130. time.tm_year -= 1900;
  131. time.tm_mon--;
  132. wpt->SetCreationTime(mkgmtime(&time), milliseconds);
  133. switch (what) {
  134. case STM_WAYPT:
  135. waypt_add(wpt);
  136. if (global_opts.objective == rtedata) {
  137. if (route == NULL) {
  138. route = route_head_alloc();
  139. route_add_head(route);
  140. }
  141. route_add_wpt(route, new Waypoint(*wpt));
  142. }
  143. break;
  144. case STM_TRKPT:
  145. if (track == NULL) {
  146. track = route_head_alloc();
  147. track_add_head(track);
  148. }
  149. track_add_wpt(track, wpt);
  150. break;
  151. }
  152. wpt = NULL;
  153. }
  154. }
  155. }
  156. static void
  157. stmwpp_rw_init(const QString& fname)
  158. {
  159. fout = gbfopen(fname, "wb", MYNAME);
  160. short_h = mkshort_new_handle();
  161. }
  162. static void
  163. stmwpp_rw_deinit(void)
  164. {
  165. mkshort_del_handle(&short_h);
  166. gbfclose(fout);
  167. }
  168. static void
  169. stmwpp_track_hdr(const route_head* track)
  170. {
  171. track_num++;
  172. }
  173. static void
  174. stmwpp_write_double(const double val)
  175. {
  176. char buff[64];
  177. char* c;
  178. c = buff + snprintf(buff, sizeof(buff), "%3.7f", val);
  179. while (*--c == '0') {
  180. *c = '\0';
  181. }
  182. if (*c == '.') {
  183. *++c = '0';
  184. }
  185. gbfprintf(fout, "%s,", buff);
  186. }
  187. static void
  188. stmwpp_waypt_cb(const Waypoint* wpt)
  189. {
  190. char cdate[16], ctime[16];
  191. struct tm tm;
  192. if (track_index != track_num) {
  193. return;
  194. }
  195. const time_t tt = wpt->GetCreationTime().toTime_t();
  196. tm = *gmtime(&tt);
  197. tm.tm_year += 1900;
  198. tm.tm_mon++;
  199. snprintf(cdate, sizeof(cdate), "%02d/%02d/%04d", tm.tm_mon, tm.tm_mday, tm.tm_year);
  200. snprintf(ctime, sizeof(ctime), "%02d:%02d:%02d", tm.tm_hour, tm.tm_min, tm.tm_sec);
  201. QString sn;
  202. switch (what) {
  203. case STM_WAYPT:
  204. case STM_RTEPT:
  205. if (global_opts.synthesize_shortnames) {
  206. sn = mkshort_from_wpt(short_h, wpt);
  207. } else {
  208. sn = mkshort(short_h, wpt->shortname);
  209. }
  210. gbfprintf(fout, "WP,D,%s,", CSTRc(sn));
  211. break;
  212. case STM_TRKPT:
  213. gbfprintf(fout, "TP,D,");
  214. break;
  215. }
  216. stmwpp_write_double(wpt->latitude);
  217. stmwpp_write_double(wpt->longitude);
  218. gbfprintf(fout, "%s,%s", cdate, ctime);
  219. switch (what) {
  220. case STM_WAYPT:
  221. case STM_RTEPT:
  222. gbfprintf(fout, ".%02d", 0);
  223. break;
  224. case STM_TRKPT:
  225. gbfprintf(fout, ".%03d", wpt->GetCreationTime().time().msec());
  226. break;
  227. }
  228. gbfprintf(fout, ",\r\n");
  229. }
  230. static void
  231. stmwpp_data_write(void)
  232. {
  233. setshort_length(short_h, 100);
  234. setshort_badchars(short_h, ",\r\n");
  235. setshort_mustupper(short_h, 0);
  236. setshort_mustuniq(short_h, 0);
  237. setshort_whitespace_ok(short_h, 1);
  238. setshort_repeating_whitespace_ok(short_h, 1);
  239. track_num = 0;
  240. if (index_opt != NULL) {
  241. track_index = atoi(index_opt);
  242. } else {
  243. track_index = 1;
  244. }
  245. gbfprintf(fout, "Datum,WGS 84,WGS 84,0,0,0,0,0\r\n");
  246. switch (global_opts.objective) {
  247. case wptdata:
  248. case unknown_gpsdata:
  249. what = STM_WAYPT;
  250. track_index = track_num; /* disable filter */
  251. setshort_defname(short_h, "WPT");
  252. waypt_disp_all(stmwpp_waypt_cb);
  253. break;
  254. case rtedata:
  255. what = STM_RTEPT;
  256. setshort_defname(short_h, "RPT");
  257. route_disp_all(stmwpp_track_hdr, NULL, stmwpp_waypt_cb);
  258. break;
  259. case trkdata:
  260. what = STM_TRKPT;
  261. track_disp_all(stmwpp_track_hdr, NULL, stmwpp_waypt_cb);
  262. break;
  263. case posndata:
  264. fatal(MYNAME ": Realtime positioning not supported.\n");
  265. break;
  266. }
  267. }
  268. ff_vecs_t stmwpp_vecs = {
  269. ff_type_file,
  270. FF_CAP_RW_ALL,
  271. stmwpp_rd_init,
  272. stmwpp_rw_init,
  273. stmwpp_rd_deinit,
  274. stmwpp_rw_deinit,
  275. stmwpp_data_read,
  276. stmwpp_data_write,
  277. NULL,
  278. stmwpp_args,
  279. CET_CHARSET_MS_ANSI, 0
  280. };
  281. #endif /* CSVFMTS_ENABLED */