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.

264 lines
6.1KB

  1. /*
  2. Support for IGN Rando track files.
  3. Copyright (C) 2005,2006 Olaf Klein, o.b.klein@gpsbabel.org
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
  15. */
  16. #include "defs.h"
  17. #include "xmlgeneric.h"
  18. #include <QtCore/QXmlStreamAttributes>
  19. #include <stdio.h>
  20. #define MYNAME "IGNRando"
  21. static gbfile* fout;
  22. static route_head* track;
  23. static Waypoint* wpt;
  24. static int track_index; /* index of track we'll write */
  25. static int track_num; /* current index of track within track_disp_all */
  26. static int xmlpoints;
  27. /* options */
  28. static char* index_opt = NULL;
  29. static arglist_t ignr_args[] = {
  30. {"index", &index_opt, "Index of track to write (if more than one in source)", NULL, ARGTYPE_INT, "1", NULL },
  31. ARG_TERMINATOR
  32. };
  33. static xg_callback ignr_start;
  34. static xg_callback ignr_nb_etapes, ignr_descr;
  35. static xg_callback ignr_etape_begin, ignr_etape_end;
  36. static xg_callback ignr_etape_pos, ignr_etape_alt;
  37. static
  38. xg_tag_mapping ignr_xml_map[] = {
  39. { ignr_start, cb_start, "/RANDONNEE" },
  40. { ignr_nb_etapes, cb_cdata, "/RANDONNEE/INFORMATIONS/NB_ETAPES" },
  41. { ignr_descr, cb_cdata, "/RANDONNEE/INFORMATIONS/DESCRIPTION" },
  42. { ignr_etape_begin, cb_start, "/RANDONNEE/ETAPE" },
  43. { ignr_etape_end, cb_end, "/RANDONNEE/ETAPE" },
  44. { ignr_etape_pos, cb_cdata, "/RANDONNEE/ETAPE/POSITION" },
  45. { ignr_etape_alt, cb_cdata, "/RANDONNEE/ETAPE/ALTITUDE" },
  46. { NULL, (xg_cb_type)0, NULL }
  47. };
  48. static void
  49. ignr_xml_error(int condition)
  50. {
  51. if (condition != 0) {
  52. fatal(MYNAME ": Error in XML structure!\n");
  53. }
  54. }
  55. /* xmlgeneric callbacks */
  56. static xg_callback ignr_start;
  57. static xg_callback ignr_nb_etapes, ignr_descr;
  58. static xg_callback ignr_etape_begin, ignr_etape_end;
  59. static void
  60. ignr_start(xg_string args, const QXmlStreamAttributes* attrv)
  61. {
  62. ignr_xml_error((track != NULL));
  63. track = route_head_alloc();
  64. track_add_head(track);
  65. }
  66. static void
  67. ignr_nb_etapes(xg_string args, const QXmlStreamAttributes* attrv)
  68. {
  69. xmlpoints = args.toInt();
  70. }
  71. static void
  72. ignr_descr(xg_string args, const QXmlStreamAttributes* attrv)
  73. {
  74. ignr_xml_error((track == NULL));
  75. track->rte_desc = args;
  76. }
  77. static void
  78. ignr_etape_begin(xg_string args, const QXmlStreamAttributes* attrv)
  79. {
  80. ignr_xml_error((wpt != NULL));
  81. wpt = new Waypoint;
  82. }
  83. static void
  84. ignr_etape_end(xg_string args, const QXmlStreamAttributes* attrv)
  85. {
  86. ignr_xml_error((track == NULL) || (wpt == NULL));
  87. track_add_wpt(track, wpt);
  88. wpt = NULL;
  89. }
  90. static void
  91. ignr_etape_pos(xg_string args, const QXmlStreamAttributes* attrv)
  92. {
  93. ignr_xml_error((wpt == NULL) || (args.isEmpty()));
  94. if (2 != sscanf(CSTRc(args), "%lf,%lf", &wpt->latitude, &wpt->longitude)) {
  95. fatal(MYNAME ": Invalid coordinates \"%s\"!\n", qPrintable(args));
  96. }
  97. }
  98. static void
  99. ignr_etape_alt(xg_string args, const QXmlStreamAttributes* attrv)
  100. {
  101. ignr_xml_error((wpt == NULL));
  102. if (args == NULL) {
  103. return;
  104. }
  105. if (1 != sscanf(CSTRc(args), "%lf", &wpt->altitude)) {
  106. fatal(MYNAME ": Invalid altitude \"%s\"!\n", qPrintable(args));
  107. }
  108. }
  109. /* callbacks registered in ignr_vecs */
  110. static void
  111. ignr_rd_init(const QString& fname)
  112. {
  113. xml_init(fname, ignr_xml_map, NULL);
  114. wpt = NULL;
  115. track = NULL;
  116. }
  117. static void
  118. ignr_rd_deinit(void)
  119. {
  120. xml_deinit();
  121. }
  122. static void
  123. ignr_read(void)
  124. {
  125. xml_read();
  126. }
  127. /* write support */
  128. /* callbacks registered in ignr_vecs */
  129. static void
  130. ignr_rw_init(const QString& fname)
  131. {
  132. fout = gbfopen(fname, "w", MYNAME);
  133. }
  134. static void
  135. ignr_rw_deinit(void)
  136. {
  137. gbfclose(fout);
  138. }
  139. static void
  140. ignr_write_track_hdr(const route_head* track)
  141. {
  142. track_num++;
  143. if (track_num != track_index) {
  144. return;
  145. }
  146. gbfprintf(fout, "\t<INFORMATIONS>\n");
  147. gbfprintf(fout, "\t\t<NB_ETAPES>%d</NB_ETAPES>\n", track->rte_waypt_ct);
  148. if (track->rte_desc != NULL) {
  149. gbfprintf(fout, "\t\t<DESCRIPTION>%s</DESCRIPTION>\n", CSTRc(track->rte_desc));
  150. }
  151. gbfprintf(fout, "\t</INFORMATIONS>\n");
  152. }
  153. static void
  154. ignr_write_track_trl(const route_head* track)
  155. {
  156. }
  157. static void
  158. ignr_write_waypt(const Waypoint* wpt)
  159. {
  160. if (track_num != track_index) {
  161. return;
  162. }
  163. gbfprintf(fout, "\t<ETAPE>\n");
  164. gbfprintf(fout, "\t\t<POSITION>%3.6f,%3.6f</POSITION>\n", wpt->latitude, wpt->longitude);
  165. if (wpt->altitude != unknown_alt) {
  166. gbfprintf(fout, "\t\t<ALTITUDE>%3.6f</ALTITUDE>\n", wpt->altitude);
  167. }
  168. gbfprintf(fout, "\t</ETAPE>\n");
  169. }
  170. static void
  171. ignr_write(void)
  172. {
  173. time_t now;
  174. struct tm tm;
  175. char buff[32];
  176. if (index_opt != NULL) {
  177. track_index = atoi(index_opt);
  178. if ((track_index < 1) || (track_index > (int) track_count()))
  179. fatal(MYNAME ": Invalid track index %d (we have currently %d track(s))!\n",
  180. track_index, track_count());
  181. } else {
  182. track_index = 1;
  183. }
  184. track_num = 0;
  185. now = current_time().toTime_t();
  186. tm = *localtime(&now);
  187. gbfprintf(fout, "<?xml version=\"1.0\" encoding=\"windows-1252\"?>\n");
  188. gbfprintf(fout, "<RANDONNEE>\n");
  189. gbfprintf(fout, "\t<ENTETE>\n");
  190. gbfprintf(fout, "\t\t<VERSION_XML>1.1</VERSION_XML>\n");
  191. gbfprintf(fout, "\t\t<VERSION_BASE>IHA03AA</VERSION_BASE>\n");
  192. strftime(buff, sizeof(buff), "%d/%m/%Y", &tm);
  193. gbfprintf(fout, "\t\t<DATE>%s</DATE>\n", buff);
  194. strftime(buff, sizeof(buff), "%H:%M:%S", &tm);
  195. gbfprintf(fout, "\t\t<HEURE>%s</HEURE>\n", buff);
  196. gbfprintf(fout, "\t</ENTETE>\n");
  197. track_disp_all(ignr_write_track_hdr, ignr_write_track_trl, ignr_write_waypt);
  198. gbfprintf(fout, "</RANDONNEE>\n");
  199. }
  200. ff_vecs_t ignr_vecs = {
  201. ff_type_file,
  202. { ff_cap_none, (ff_cap)(ff_cap_read | ff_cap_write), ff_cap_none },
  203. ignr_rd_init,
  204. ignr_rw_init,
  205. ignr_rd_deinit,
  206. ignr_rw_deinit,
  207. ignr_read,
  208. ignr_write,
  209. NULL,
  210. ignr_args,
  211. CET_CHARSET_MS_ANSI, 1
  212. };