maz
2015-08-15 11:58:06 UTC
Large waypoint lists are organized into blocks of at most
WAYPOINTS_PER_BLOCK (128) POIs in generated GPI files for performance
reasons.
It appears that at least on older Garmin Nuvi devices, proximity alerts
often do not work (they do not show up as Custom POIs) and POI lists get
mangled (even to the point of crashing the unit) when there are several
such blocks, particularly with large lists of isolated waypoints.
This problem is the result of wdata_check() which may leave empty
nodes in the tree after sorting waypoints. These nodes show up as empty
blocks in the output file and are not well handled by some devices.
Preventing wdata_compute_size() and wdata_write() from issuing empty
blocks solves the issue.
Fixes: 26840523d411 ("Add support for multiple POI lists to writer code.")
Signed-off-by: maz <***@p0d.org>
---
gpsbabel/garmin_gpi.cc | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/gpsbabel/garmin_gpi.cc b/gpsbabel/garmin_gpi.cc
index 17e18f7..cae6f1d 100644
--- a/gpsbabel/garmin_gpi.cc
+++ b/gpsbabel/garmin_gpi.cc
@@ -883,7 +883,10 @@ static int
wdata_compute_size(writer_data_t* data)
{
queue* elem, *tmp;
- int res;
+ int res = 0;
+
+ if (QUEUE_EMPTY(&data->Q))
+ goto skip_empty_block; /* do not issue an empty block */
res = 23; /* bounds, ... of tag 0x80008 */
@@ -1009,6 +1012,8 @@ wdata_compute_size(writer_data_t* data)
}
}
+skip_empty_block:
+
if (data->top_left) {
res += wdata_compute_size(data->top_left);
}
@@ -1024,6 +1029,9 @@ wdata_compute_size(writer_data_t* data)
data->sz = res;
+ if (QUEUE_EMPTY(&data->Q))
+ return res;
+
return res + 12; /* + 12 = caller needs info about tag header size */
}
@@ -1033,6 +1041,9 @@ wdata_write(const writer_data_t* data)
{
queue* elem, *tmp;
+ if (QUEUE_EMPTY(&data->Q))
+ goto skip_empty_block; /* do not issue an empty block */
+
gbfputint32(0x80008, fout);
gbfputint32(data->sz, fout);
gbfputint32(23, fout); /* bounds + three bytes */
@@ -1155,6 +1166,8 @@ wdata_write(const writer_data_t* data)
}
}
+skip_empty_block:
+
if (data->top_left) {
wdata_write(data->top_left);
}
WAYPOINTS_PER_BLOCK (128) POIs in generated GPI files for performance
reasons.
It appears that at least on older Garmin Nuvi devices, proximity alerts
often do not work (they do not show up as Custom POIs) and POI lists get
mangled (even to the point of crashing the unit) when there are several
such blocks, particularly with large lists of isolated waypoints.
This problem is the result of wdata_check() which may leave empty
nodes in the tree after sorting waypoints. These nodes show up as empty
blocks in the output file and are not well handled by some devices.
Preventing wdata_compute_size() and wdata_write() from issuing empty
blocks solves the issue.
Fixes: 26840523d411 ("Add support for multiple POI lists to writer code.")
Signed-off-by: maz <***@p0d.org>
---
gpsbabel/garmin_gpi.cc | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/gpsbabel/garmin_gpi.cc b/gpsbabel/garmin_gpi.cc
index 17e18f7..cae6f1d 100644
--- a/gpsbabel/garmin_gpi.cc
+++ b/gpsbabel/garmin_gpi.cc
@@ -883,7 +883,10 @@ static int
wdata_compute_size(writer_data_t* data)
{
queue* elem, *tmp;
- int res;
+ int res = 0;
+
+ if (QUEUE_EMPTY(&data->Q))
+ goto skip_empty_block; /* do not issue an empty block */
res = 23; /* bounds, ... of tag 0x80008 */
@@ -1009,6 +1012,8 @@ wdata_compute_size(writer_data_t* data)
}
}
+skip_empty_block:
+
if (data->top_left) {
res += wdata_compute_size(data->top_left);
}
@@ -1024,6 +1029,9 @@ wdata_compute_size(writer_data_t* data)
data->sz = res;
+ if (QUEUE_EMPTY(&data->Q))
+ return res;
+
return res + 12; /* + 12 = caller needs info about tag header size */
}
@@ -1033,6 +1041,9 @@ wdata_write(const writer_data_t* data)
{
queue* elem, *tmp;
+ if (QUEUE_EMPTY(&data->Q))
+ goto skip_empty_block; /* do not issue an empty block */
+
gbfputint32(0x80008, fout);
gbfputint32(data->sz, fout);
gbfputint32(23, fout); /* bounds + three bytes */
@@ -1155,6 +1166,8 @@ wdata_write(const writer_data_t* data)
}
}
+skip_empty_block:
+
if (data->top_left) {
wdata_write(data->top_left);
}
--
1.8.4
------------------------------------------------------------------------------
1.8.4
------------------------------------------------------------------------------