diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/README myth.20746.0626b/mythtv/libs/libmythhdhomerun/README
--- mythtv/libs/libmythhdhomerun/README	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/README	2009-06-27 10:32:15.000000000 -0500
@@ -1,5 +1,5 @@
 /*
- * libhdhomerun
+ * README
  *
  * Copyright © 2005-2006 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
@@ -15,6 +15,19 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 
 Top level include file: hdhomerun.h
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/README.MythTV myth.20746.0626b/mythtv/libs/libmythhdhomerun/README.MythTV
--- mythtv/libs/libmythhdhomerun/README.MythTV	1969-12-31 18:00:00.000000000 -0600
+++ mythtv/libs/libmythhdhomerun/README.MythTV	2009-06-27 10:32:15.000000000 -0500
@@ -0,0 +1,7 @@
+
+This directory contains Silicondust Engineering's hdhomerun
+library used for communicating with the HDHomeRun hardware.
+
+The files in this directory are released under the GNU LESSER GENERAL PUBLIC LICENSE
+For details see the lgpl.txt file which should be located in this directory.
+If you can not find it, it can also be seen at http://www.gnu.org/licenses/lgpl.txt
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun.h myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun.h
--- mythtv/libs/libmythhdhomerun/hdhomerun.h	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/hdhomerun.h	2009-06-27 10:32:15.000000000 -0500
@@ -1,7 +1,7 @@
 /*
- * hdhomerun_device.h
+ * hdhomerun.h
  *
- * Copyright © 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
+ * Copyright Â© 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
  * This library is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public
@@ -15,6 +15,19 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 
 #include "hdhomerun_os.h"
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_channels.c myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_channels.c
--- mythtv/libs/libmythhdhomerun/hdhomerun_channels.c	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/hdhomerun_channels.c	2009-06-27 10:32:15.000000000 -0500
@@ -1,7 +1,7 @@
 /*
- * hdhomerun_channelscan.c
+ * hdhomerun_channels.c
  *
- * Copyright © 2007-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
+ * Copyright Â© 2007-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
  * This library is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public
@@ -15,6 +15,19 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 
 #include "hdhomerun.h"
@@ -24,68 +37,146 @@
 struct hdhomerun_channel_entry_t {
 	struct hdhomerun_channel_entry_t *next;
 	struct hdhomerun_channel_entry_t *prev;
-	uint32_t channel_map;
 	uint32_t frequency;
 	uint8_t channel_number;
 	char name[16];
 };
 
-struct hdhomerun_channel_map_range_t {
-	uint32_t channel_map;
+struct hdhomerun_channel_list_t {
+	struct hdhomerun_channel_entry_t *head;
+	struct hdhomerun_channel_entry_t *tail;
+};
+
+struct hdhomerun_channelmap_range_t {
 	uint8_t channel_range_start;
 	uint8_t channel_range_end;
 	uint32_t frequency;
 	uint32_t spacing;
 };
 
-static const struct hdhomerun_channel_map_range_t hdhomerun_channels_map_ranges[] = {
-	{CHANNEL_MAP_US_BCAST,   2,   4,  57000000, 6000000},
-	{CHANNEL_MAP_US_BCAST,   5,   6,  79000000, 6000000},
-	{CHANNEL_MAP_US_BCAST,   7,  13, 177000000, 6000000},
-	{CHANNEL_MAP_US_BCAST,  14,  69, 473000000, 6000000},
-
-	{CHANNEL_MAP_US_CABLE,   1,   1,  75000000, 6000000},
-	{CHANNEL_MAP_US_CABLE,   2,   4,  57000000, 6000000},
-	{CHANNEL_MAP_US_CABLE,   5,   6,  79000000, 6000000},
-	{CHANNEL_MAP_US_CABLE,   7,  13, 177000000, 6000000},
-	{CHANNEL_MAP_US_CABLE,  14,  22, 123000000, 6000000},
-	{CHANNEL_MAP_US_CABLE,  23,  94, 219000000, 6000000},
-	{CHANNEL_MAP_US_CABLE,  95,  99,  93000000, 6000000},
-	{CHANNEL_MAP_US_CABLE, 100, 136, 651000000, 6000000},
-
-	{CHANNEL_MAP_US_HRC,     1,   1,  73753600, 6000300},
-	{CHANNEL_MAP_US_HRC,     2,   4,  55752700, 6000300},
-	{CHANNEL_MAP_US_HRC,     5,   6,  79753900, 6000300},
-	{CHANNEL_MAP_US_HRC,     7,  13, 175758700, 6000300},
-	{CHANNEL_MAP_US_HRC,    14,  22, 121756000, 6000300},
-	{CHANNEL_MAP_US_HRC,    23,  94, 217760800, 6000300},
-	{CHANNEL_MAP_US_HRC,    95,  99,  91754500, 6000300},
-	{CHANNEL_MAP_US_HRC,   100, 136, 649782400, 6000300},
-
-	{CHANNEL_MAP_US_IRC,     1,   1,  75012500, 6000000},
-	{CHANNEL_MAP_US_IRC,     2,   4,  57012500, 6000000},
-	{CHANNEL_MAP_US_IRC,     5,   6,  81012500, 6000000},
-	{CHANNEL_MAP_US_IRC,     7,  13, 177012500, 6000000},
-	{CHANNEL_MAP_US_IRC,    14,  22, 123012500, 6000000},
-	{CHANNEL_MAP_US_IRC,    23,  41, 219012500, 6000000},
-	{CHANNEL_MAP_US_IRC,    42,  42, 333025000, 6000000},
-	{CHANNEL_MAP_US_IRC,    43,  94, 339012500, 6000000},
-	{CHANNEL_MAP_US_IRC,    95,  97,  93012500, 6000000},
-	{CHANNEL_MAP_US_IRC,    98,  99, 111025000, 6000000},
-	{CHANNEL_MAP_US_IRC,   100, 136, 651012500, 6000000},
-
-	{CHANNEL_MAP_UK_BCAST,  21,  68, 474000000, 8000000},
-	{CHANNEL_MAP_NZ_BCAST,  25,  62, 506000000, 8000000},
-
-	{0,                      0,   0,         0,       0}
+struct hdhomerun_channelmap_record_t {
+	const char *channelmap_prefix;
+	const char *channelmap;
+	const struct hdhomerun_channelmap_range_t *range_list;
+	const char *channelmap_scan_group;
+	const char *countrycodes;
+};
+
+/* AU antenna channels. Channels {0, 1, 2, 6, 7, 8, 9, 9A} are numbered {2, 3, 4, 5, 6, 7, 8, 9} by the HDHomeRun. */
+static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_au_bcast[] = {
+	{  2,   2,  48500000, 7000000},
+	{  3,   4,  59500000, 7000000},
+	{  5,  12, 177500000, 7000000},
+	{ 28,  69, 529500000, 7000000},
+	{  0,   0,         0,       0}
+};
+
+/* AU cable channels. TBD. */
+static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_au_cable[] = {
+	{  0,   0,         0,       0}
+};
+
+/* EU antenna channels. */
+static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_eu_bcast[] = {
+	{  2,   4,  50500000, 7000000},
+	{  5,  12, 177500000, 7000000},
+	{ 21,  69, 474000000, 8000000},
+	{  0,   0,         0,       0}
+};
+
+/* EU cable channels. Channels do not have simple numbers - the HDHomeRun uses its own numbering scheme (subject to change). */
+static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_eu_cable[] = {
+	{  6,   7, 113000000, 8000000},
+	{  9, 100, 138000000, 8000000},
+	{  0,   0,         0,       0}
 };
 
-static struct hdhomerun_channel_entry_t *hdhomerun_channel_list_head = NULL;
-static struct hdhomerun_channel_entry_t *hdhomerun_channel_list_tail = NULL;
+/* US antenna channels. */
+static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_us_bcast[] = {
+	{  2,   4,  57000000, 6000000},
+	{  5,   6,  79000000, 6000000},
+	{  7,  13, 177000000, 6000000},
+	{ 14,  69, 473000000, 6000000},
+	{  0,   0,         0,       0}
+};
+
+/* US cable channels. */
+static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_us_cable[] = {
+	{  2,   4,  57000000, 6000000},
+	{  5,   6,  79000000, 6000000},
+	{  7,  13, 177000000, 6000000},
+	{ 14,  22, 123000000, 6000000},
+	{ 23,  94, 219000000, 6000000},
+	{ 95,  99,  93000000, 6000000},
+	{100, 135, 651000000, 6000000},
+	{  0,   0,         0,       0}
+};
+
+/* US cable channels (HRC). */
+static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_us_hrc[] = {
+	{  2,   4,  55752700, 6000300},
+	{  5,   6,  79753900, 6000300},
+	{  7,  13, 175758700, 6000300},
+	{ 14,  22, 121756000, 6000300},
+	{ 23,  94, 217760800, 6000300},
+	{ 95,  99,  91754500, 6000300},
+	{100, 135, 649782400, 6000300},
+	{  0,   0,         0,       0}
+};
 
-uint32_t hdhomerun_channel_entry_channel_map(struct hdhomerun_channel_entry_t *entry)
+/* US cable channels (IRC). */
+static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_us_irc[] = {
+	{  2,   4,  57012500, 6000000},
+	{  5,   6,  81012500, 6000000},
+	{  7,  13, 177012500, 6000000},
+	{ 14,  22, 123012500, 6000000},
+	{ 23,  41, 219012500, 6000000},
+	{ 42,  42, 333025000, 6000000},
+	{ 43,  94, 339012500, 6000000},
+	{ 95,  97,  93012500, 6000000},
+	{ 98,  99, 111025000, 6000000},
+	{100, 135, 651012500, 6000000},
+	{  0,   0,         0,       0}
+};
+
+static const struct hdhomerun_channelmap_record_t hdhomerun_channelmap_table[] = {
+	{"au", "au-bcast", hdhomerun_channelmap_range_au_bcast, "au-bcast",               "AU"},
+	{"au", "au-cable", hdhomerun_channelmap_range_au_cable, "au-cable",               "AU"},
+	{"eu", "eu-bcast", hdhomerun_channelmap_range_eu_bcast, "eu-bcast",               "EU"},
+	{"eu", "eu-cable", hdhomerun_channelmap_range_eu_cable, "eu-cable",               "EU"},
+	{"tw", "tw-bcast", hdhomerun_channelmap_range_us_bcast, "tw-bcast",               "TW"},
+	{"tw", "tw-cable", hdhomerun_channelmap_range_us_cable, "tw-cable",               "TW"},
+	{"us", "us-bcast", hdhomerun_channelmap_range_us_bcast, "us-bcast",               "CA US"},
+	{"us", "us-cable", hdhomerun_channelmap_range_us_cable, "us-cable us-hrc us-irc", "CA US"},
+	{"us", "us-hrc",   hdhomerun_channelmap_range_us_hrc  , "us-cable us-hrc us-irc", "CA US"},
+	{"us", "us-irc",   hdhomerun_channelmap_range_us_irc,   "us-cable us-hrc us-irc", "CA US"},
+	{NULL, NULL,       NULL,                                NULL,                     NULL}
+};
+
+const char *hdhomerun_channelmap_convert_countrycode_to_channelmap_prefix(const char *countrycode)
 {
-	return entry->channel_map;
+	const struct hdhomerun_channelmap_record_t *record = hdhomerun_channelmap_table;
+	while (record->channelmap) {
+		if (strstr(record->countrycodes, countrycode)) {
+			return record->channelmap_prefix;
+		}
+		record++;
+	}
+
+	return "eu";
+}
+
+const char *hdhomerun_channelmap_get_channelmap_scan_group(const char *channelmap)
+{
+	const struct hdhomerun_channelmap_record_t *record = hdhomerun_channelmap_table;
+	while (record->channelmap) {
+		if (strstr(channelmap, record->channelmap)) {
+			return record->channelmap_scan_group;
+		}
+		record++;
+	}
+
+	return NULL;
 }
 
 uint8_t hdhomerun_channel_entry_channel_number(struct hdhomerun_channel_entry_t *entry)
@@ -103,208 +194,185 @@ const char *hdhomerun_channel_entry_name
 	return entry->name;
 }
 
-static const char *hdhomerun_channel_map_name(uint32_t channel_map)
+struct hdhomerun_channel_entry_t *hdhomerun_channel_list_first(struct hdhomerun_channel_list_t *channel_list)
 {
-	switch (channel_map) {
-	case CHANNEL_MAP_US_BCAST:
-		return "us-bcast";
-	case CHANNEL_MAP_US_CABLE:
-		return "us-cable";
-	case CHANNEL_MAP_US_HRC:
-		return "us-hrc";
-	case CHANNEL_MAP_US_IRC:
-		return "us-irc";
-	case CHANNEL_MAP_UK_BCAST:
-		return "uk-bcast";
-	case CHANNEL_MAP_NZ_BCAST:
-		return "nz-bcast";
-	default:
-		return "unknown";
-	}
+	return channel_list->head;
 }
 
-static void hdhomerun_channel_list_build_insert(struct hdhomerun_channel_entry_t *entry)
+struct hdhomerun_channel_entry_t *hdhomerun_channel_list_last(struct hdhomerun_channel_list_t *channel_list)
 {
-	struct hdhomerun_channel_entry_t *prev = NULL;
-	struct hdhomerun_channel_entry_t *next = hdhomerun_channel_list_head;
-
-	while (next) {
-		if (next->frequency > entry->frequency) {
-			break;
-		}
-
-		prev = next;
-		next = next->next;
-	}
-
-	entry->prev = prev;
-	entry->next = next;
-
-	if (prev) {
-		prev->next = entry;
-	} else {
-		hdhomerun_channel_list_head = entry;
-	}
-
-	if (next) {
-		next->prev = entry;
-	} else {
-		hdhomerun_channel_list_tail = entry;
-	}
+	return channel_list->tail;
 }
 
-static void hdhomerun_channel_list_build_range(const struct hdhomerun_channel_map_range_t *range)
+struct hdhomerun_channel_entry_t *hdhomerun_channel_list_next(struct hdhomerun_channel_list_t *channel_list, struct hdhomerun_channel_entry_t *entry)
 {
-	uint8_t channel_number;
-	for (channel_number = range->channel_range_start; channel_number <= range->channel_range_end; channel_number++) {
-		struct hdhomerun_channel_entry_t *entry = (struct hdhomerun_channel_entry_t *)calloc(1, sizeof(struct hdhomerun_channel_entry_t));
-		if (!entry) {
-			return;
-		}
-
-		entry->channel_map = range->channel_map;
-		entry->channel_number = channel_number;
-		entry->frequency = range->frequency + ((uint32_t)(channel_number - range->channel_range_start) * range->spacing);
-		entry->frequency = (entry->frequency / FREQUENCY_RESOLUTION) * FREQUENCY_RESOLUTION;
-		sprintf(entry->name, "%s:%u", hdhomerun_channel_map_name(entry->channel_map), entry->channel_number);
-
-		hdhomerun_channel_list_build_insert(entry);
-	}
+	return entry->next;
 }
 
-static void hdhomerun_channel_list_build(void)
+struct hdhomerun_channel_entry_t *hdhomerun_channel_list_prev(struct hdhomerun_channel_list_t *channel_list, struct hdhomerun_channel_entry_t *entry)
 {
-	const struct hdhomerun_channel_map_range_t *range = hdhomerun_channels_map_ranges;
-	while (range->channel_map) {
-		hdhomerun_channel_list_build_range(range);
-		range++;
-	}
+	return entry->prev;
 }
 
-struct hdhomerun_channel_entry_t *hdhomerun_channel_list_first(uint32_t channel_map)
+uint32_t hdhomerun_channel_list_total_count(struct hdhomerun_channel_list_t *channel_list)
 {
-	if (!hdhomerun_channel_list_head) {
-		hdhomerun_channel_list_build();
-	}
+	uint32_t count = 0;
 
-	struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_head;
+	struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_first(channel_list);
 	while (entry) {
-		if (entry->channel_map & channel_map) {
-			return entry;
-		}
-
-		entry = entry->next;
+		count++;
+		entry = hdhomerun_channel_list_next(channel_list, entry);
 	}
 
-	return NULL;
+	return count;
 }
 
-struct hdhomerun_channel_entry_t *hdhomerun_channel_list_last(uint32_t channel_map)
+uint32_t hdhomerun_channel_list_frequency_count(struct hdhomerun_channel_list_t *channel_list)
 {
-	if (!hdhomerun_channel_list_head) {
-		hdhomerun_channel_list_build();
-	}
+	uint32_t count = 0;
+	uint32_t last_frequency = 0;
 
-	struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_tail;
+	struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_first(channel_list);
 	while (entry) {
-		if (entry->channel_map & channel_map) {
-			return entry;
+		if (entry->frequency != last_frequency) {
+			last_frequency = entry->frequency;
+			count++;
 		}
 
-		entry = entry->prev;
+		entry = hdhomerun_channel_list_next(channel_list, entry);
 	}
 
-	return NULL;
+	return count;
+}
+
+uint32_t hdhomerun_channel_frequency_truncate(uint32_t frequency)
+{
+	return (frequency / FREQUENCY_RESOLUTION) * FREQUENCY_RESOLUTION;
 }
 
-struct hdhomerun_channel_entry_t *hdhomerun_channel_list_next(uint32_t channel_map, struct hdhomerun_channel_entry_t *entry)
+uint32_t hdhomerun_channel_number_to_frequency(struct hdhomerun_channel_list_t *channel_list, uint8_t channel_number)
 {
-	entry = entry->next;
+	struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_first(channel_list);
 	while (entry) {
-		if (entry->channel_map & channel_map) {
-			return entry;
+		if (entry->channel_number == channel_number) {
+			return entry->frequency;
 		}
 
-		entry = entry->next;
+		entry = hdhomerun_channel_list_next(channel_list, entry);
 	}
 
-	return NULL;
+	return 0;
 }
 
-struct hdhomerun_channel_entry_t *hdhomerun_channel_list_prev(uint32_t channel_map, struct hdhomerun_channel_entry_t *entry)
+uint8_t hdhomerun_channel_frequency_to_number(struct hdhomerun_channel_list_t *channel_list, uint32_t frequency)
 {
-	entry = entry->prev;
+	frequency = hdhomerun_channel_frequency_truncate(frequency);
+
+	struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_first(channel_list);
 	while (entry) {
-		if (entry->channel_map & channel_map) {
-			return entry;
+		if (entry->frequency == frequency) {
+			return entry->channel_number;
+		}
+		if (entry->frequency > frequency) {
+			return 0;
 		}
 
-		entry = entry->prev;
+		entry = hdhomerun_channel_list_next(channel_list, entry);
 	}
 
-	return NULL;
+	return 0;
 }
 
-uint32_t hdhomerun_channel_list_total_count(uint32_t channel_map)
+static void hdhomerun_channel_list_build_insert(struct hdhomerun_channel_list_t *channel_list, struct hdhomerun_channel_entry_t *entry)
 {
-	uint32_t count = 0;
+	struct hdhomerun_channel_entry_t *prev = NULL;
+	struct hdhomerun_channel_entry_t *next = channel_list->head;
 
-	struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_first(channel_map);
-	while (entry) {
-		count++;
-		entry = hdhomerun_channel_list_next(channel_map, entry);
+	while (next) {
+		if (next->frequency > entry->frequency) {
+			break;
+		}
+
+		prev = next;
+		next = next->next;
 	}
 
-	return count;
+	entry->prev = prev;
+	entry->next = next;
+
+	if (prev) {
+		prev->next = entry;
+	} else {
+		channel_list->head = entry;
+	}
+
+	if (next) {
+		next->prev = entry;
+	} else {
+		channel_list->tail = entry;
+	}
 }
 
-uint32_t hdhomerun_channel_list_frequency_count(uint32_t channel_map)
+static void hdhomerun_channel_list_build_range(struct hdhomerun_channel_list_t *channel_list, const char *channelmap, const struct hdhomerun_channelmap_range_t *range)
 {
-	uint32_t count = 0;
-	uint32_t last_frequency = 0;
-
-	struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_first(channel_map);
-	while (entry) {
-		if (entry->frequency != last_frequency) {
-			last_frequency = entry->frequency;
-			count++;
+	uint8_t channel_number;
+	for (channel_number = range->channel_range_start; channel_number <= range->channel_range_end; channel_number++) {
+		struct hdhomerun_channel_entry_t *entry = (struct hdhomerun_channel_entry_t *)calloc(1, sizeof(struct hdhomerun_channel_entry_t));
+		if (!entry) {
+			return;
 		}
 
-		entry = hdhomerun_channel_list_next(channel_map, entry);
-	}
+		entry->channel_number = channel_number;
+		entry->frequency = range->frequency + ((uint32_t)(channel_number - range->channel_range_start) * range->spacing);
+		entry->frequency = hdhomerun_channel_frequency_truncate(entry->frequency);
+		sprintf(entry->name, "%s:%u", channelmap, entry->channel_number);
 
-	return count;
+		hdhomerun_channel_list_build_insert(channel_list, entry);
+	}
 }
 
-uint32_t hdhomerun_channel_number_to_frequency(uint32_t channel_map, uint8_t channel_number)
+static void hdhomerun_channel_list_build_ranges(struct hdhomerun_channel_list_t *channel_list, const struct hdhomerun_channelmap_record_t *record)
 {
-	struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_first(channel_map);
-	while (entry) {
-		if (entry->channel_number == channel_number) {
-			return entry->frequency;
-		}
+	const struct hdhomerun_channelmap_range_t *range = record->range_list;
+	while (range->frequency) {
+		hdhomerun_channel_list_build_range(channel_list, record->channelmap, range);
+		range++;
+	}
+}
 
-		entry = hdhomerun_channel_list_next(channel_map, entry);
+void hdhomerun_channel_list_destroy(struct hdhomerun_channel_list_t *channel_list)
+{
+	while (channel_list->head) {
+		struct hdhomerun_channel_entry_t *entry = channel_list->head;
+		channel_list->head = entry->next;
+		free(entry);
 	}
 
-	return 0;
+	free(channel_list);
 }
 
-uint8_t hdhomerun_channel_frequency_to_number(uint32_t channel_map, uint32_t frequency)
+struct hdhomerun_channel_list_t *hdhomerun_channel_list_create(const char *channelmap)
 {
-	frequency = (frequency / FREQUENCY_RESOLUTION) * FREQUENCY_RESOLUTION;
+	struct hdhomerun_channel_list_t *channel_list = (struct hdhomerun_channel_list_t *)calloc(1, sizeof(struct hdhomerun_channel_list_t));
+	if (!channel_list) {
+		return NULL;
+	}
 
-	struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_first(channel_map);
-	while (entry) {
-		if (entry->frequency == frequency) {
-			return entry->channel_number;
-		}
-		if (entry->frequency > frequency) {
-			return 0;
+	const struct hdhomerun_channelmap_record_t *record = hdhomerun_channelmap_table;
+	while (record->channelmap) {
+		if (!strstr(channelmap, record->channelmap)) {
+			record++;
+			continue;
 		}
 
-		entry = hdhomerun_channel_list_next(channel_map, entry);
+		hdhomerun_channel_list_build_ranges(channel_list, record);
+		record++;
 	}
 
-	return 0;
+	if (!channel_list->head) {
+		free(channel_list);
+		return NULL;
+	}
+
+	return channel_list;
 }
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_channels.h myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_channels.h
--- mythtv/libs/libmythhdhomerun/hdhomerun_channels.h	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/hdhomerun_channels.h	2009-06-27 10:32:15.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * hdhomerun_channels.h
  *
- * Copyright © 2007-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
+ * Copyright Â© 2007-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
  * This library is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public
@@ -15,30 +15,49 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 
-#define CHANNEL_MAP_US_BCAST (1 << 0)
-#define CHANNEL_MAP_US_CABLE (1 << 1)
-#define CHANNEL_MAP_US_HRC (1 << 2)
-#define CHANNEL_MAP_US_IRC (1 << 3)
-#define CHANNEL_MAP_US_ALL (CHANNEL_MAP_US_BCAST | CHANNEL_MAP_US_CABLE | CHANNEL_MAP_US_HRC | CHANNEL_MAP_US_IRC)
-
-#define CHANNEL_MAP_UK_BCAST (1 << 4)
-#define CHANNEL_MAP_NZ_BCAST (1 << 5)
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 struct hdhomerun_channel_entry_t;
+struct hdhomerun_channel_list_t;
+
+extern LIBTYPE const char *hdhomerun_channelmap_convert_countrycode_to_channelmap_prefix(const char *countrycode);
+extern LIBTYPE const char *hdhomerun_channelmap_get_channelmap_scan_group(const char *channelmap);
 
-extern LIBTYPE uint32_t hdhomerun_channel_entry_channel_map(struct hdhomerun_channel_entry_t *entry);
 extern LIBTYPE uint8_t hdhomerun_channel_entry_channel_number(struct hdhomerun_channel_entry_t *entry);
 extern LIBTYPE uint32_t hdhomerun_channel_entry_frequency(struct hdhomerun_channel_entry_t *entry);
 extern LIBTYPE const char *hdhomerun_channel_entry_name(struct hdhomerun_channel_entry_t *entry);
 
-extern LIBTYPE struct hdhomerun_channel_entry_t *hdhomerun_channel_list_first(uint32_t channel_map);
-extern LIBTYPE struct hdhomerun_channel_entry_t *hdhomerun_channel_list_last(uint32_t channel_map);
-extern LIBTYPE struct hdhomerun_channel_entry_t *hdhomerun_channel_list_next(uint32_t channel_map, struct hdhomerun_channel_entry_t *entry);
-extern LIBTYPE struct hdhomerun_channel_entry_t *hdhomerun_channel_list_prev(uint32_t channel_map, struct hdhomerun_channel_entry_t *entry);
-extern LIBTYPE uint32_t hdhomerun_channel_list_total_count(uint32_t channel_map);
-extern LIBTYPE uint32_t hdhomerun_channel_list_frequency_count(uint32_t channel_map);
+extern LIBTYPE struct hdhomerun_channel_list_t *hdhomerun_channel_list_create(const char *channelmap);
+extern LIBTYPE void hdhomerun_channel_list_destroy(struct hdhomerun_channel_list_t *channel_list);
 
-extern LIBTYPE uint32_t hdhomerun_channel_number_to_frequency(uint32_t channel_map, uint8_t channel_number);
-extern LIBTYPE uint8_t hdhomerun_channel_frequency_to_number(uint32_t channel_map, uint32_t frequency);
+extern LIBTYPE struct hdhomerun_channel_entry_t *hdhomerun_channel_list_first(struct hdhomerun_channel_list_t *channel_list);
+extern LIBTYPE struct hdhomerun_channel_entry_t *hdhomerun_channel_list_last(struct hdhomerun_channel_list_t *channel_list);
+extern LIBTYPE struct hdhomerun_channel_entry_t *hdhomerun_channel_list_next(struct hdhomerun_channel_list_t *channel_list, struct hdhomerun_channel_entry_t *entry);
+extern LIBTYPE struct hdhomerun_channel_entry_t *hdhomerun_channel_list_prev(struct hdhomerun_channel_list_t *channel_list, struct hdhomerun_channel_entry_t *entry);
+extern LIBTYPE uint32_t hdhomerun_channel_list_total_count(struct hdhomerun_channel_list_t *channel_list);
+extern LIBTYPE uint32_t hdhomerun_channel_list_frequency_count(struct hdhomerun_channel_list_t *channel_list);
+
+extern LIBTYPE uint32_t hdhomerun_channel_frequency_truncate(uint32_t frequency);
+extern LIBTYPE uint32_t hdhomerun_channel_number_to_frequency(struct hdhomerun_channel_list_t *channel_list, uint8_t channel_number);
+extern LIBTYPE uint8_t hdhomerun_channel_frequency_to_number(struct hdhomerun_channel_list_t *channel_list, uint32_t frequency);
+
+#ifdef __cplusplus
+}
+#endif
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_channelscan.c myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_channelscan.c
--- mythtv/libs/libmythhdhomerun/hdhomerun_channelscan.c	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/hdhomerun_channelscan.c	2009-06-27 10:32:15.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * hdhomerun_channelscan.c
  *
- * Copyright © 2007-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
+ * Copyright Â© 2007-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
  * This library is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public
@@ -15,19 +15,31 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 
 #include "hdhomerun.h"
 
 struct hdhomerun_channelscan_t {
 	struct hdhomerun_device_t *hd;
-	uint32_t channel_map;
-	uint32_t options;
 	uint32_t scanned_channels;
+	struct hdhomerun_channel_list_t *channel_list;	
 	struct hdhomerun_channel_entry_t *next_channel;
 };
 
-struct hdhomerun_channelscan_t *channelscan_create(struct hdhomerun_device_t *hd, uint32_t channel_map, uint32_t options)
+struct hdhomerun_channelscan_t *channelscan_create(struct hdhomerun_device_t *hd, const char *channelmap)
 {
 	struct hdhomerun_channelscan_t *scan = (struct hdhomerun_channelscan_t *)calloc(1, sizeof(struct hdhomerun_channelscan_t));
 	if (!scan) {
@@ -35,15 +47,14 @@ struct hdhomerun_channelscan_t *channels
 	}
 
 	scan->hd = hd;
-	scan->channel_map = channel_map;
-	scan->options = options;
 
-	if (scan->options & HDHOMERUN_CHANNELSCAN_OPTION_REVERSE) {
-		scan->next_channel = hdhomerun_channel_list_last(channel_map);
-	} else {
-		scan->next_channel = hdhomerun_channel_list_first(channel_map);
+	scan->channel_list = hdhomerun_channel_list_create(channelmap);
+	if (!scan->channel_list) {
+		free(scan);
+		return NULL;
 	}
 
+	scan->next_channel = hdhomerun_channel_list_last(scan->channel_list);
 	return scan;
 }
 
@@ -52,15 +63,6 @@ void channelscan_destroy(struct hdhomeru
 	free(scan);
 }
 
-static struct hdhomerun_channel_entry_t *channelscan_advance_channel_internal(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channel_entry_t *entry)
-{
-	if (scan->options & HDHOMERUN_CHANNELSCAN_OPTION_REVERSE) {
-		return hdhomerun_channel_list_prev(scan->channel_map, entry);
-	} else {
-		return hdhomerun_channel_list_next(scan->channel_map, entry);
-	}
-}
-
 static int channelscan_execute_find_lock(struct hdhomerun_channelscan_t *scan, uint32_t frequency, struct hdhomerun_channelscan_result_t *result)
 {
 	/* Set channel. */
@@ -100,6 +102,41 @@ static int channelscan_execute_find_lock
 	return 1;
 }
 
+static void channelscan_extract_name(struct hdhomerun_channelscan_program_t *program, const char *line)
+{
+	/* Find start of name. */
+	const char *start = strchr(line, ' ');
+	if (!start) {
+		return;
+	}
+	start++;
+
+	start = strchr(start, ' ');
+	if (!start) {
+		return;
+	}
+	start++;
+
+	/* Find end of name. */
+	const char *end = strstr(start, " (");
+	if (!end) {
+		end = strchr(line, 0);
+	}
+
+	if (end <= start) {
+		return;
+	}
+
+	/* Extract name. */
+	size_t length = (size_t)(end - start);
+	if (length > sizeof(program->name) - 1) {
+		length = sizeof(program->name) - 1;
+	}
+
+	strncpy(program->name, start, length);
+	program->name[length] = 0;
+}
+
 static int channelscan_execute_detect_programs(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result, int *pchanged)
 {
 	*pchanged = FALSE;
@@ -129,19 +166,15 @@ static int channelscan_execute_detect_pr
 
 		unsigned int program_number;
 		unsigned int virtual_major, virtual_minor;
-		if (sscanf(line, "%u: %u.%u %7s", &program_number, &virtual_major, &virtual_minor, program.name) != 4) {
-			if (sscanf(line, "%u: %u.%u", &program_number, &virtual_major, &virtual_minor) != 3) {
-				continue;
-			}
+		if (sscanf(line, "%u: %u.%u", &program_number, &virtual_major, &virtual_minor) != 3) {
+			continue;
 		}
 
 		program.program_number = program_number;
 		program.virtual_major = virtual_major;
 		program.virtual_minor = virtual_minor;
 
-		if (program.name[0] == '(') {
-			memset(program.name, 0, sizeof(program.name));
-		}
+		channelscan_extract_name(&program, line);
 
 		program.type = HDHOMERUN_CHANNELSCAN_PROGRAM_NORMAL;
 		if (strstr(line, "(no data)")) {
@@ -186,11 +219,11 @@ int channelscan_advance(struct hdhomerun
 
 	/* Combine channels with same frequency. */
 	result->frequency = hdhomerun_channel_entry_frequency(entry);
-	result->channel_map = hdhomerun_channel_entry_channel_map(entry);
-	strcpy(result->channel_str, hdhomerun_channel_entry_name(entry));
+	strncpy(result->channel_str, hdhomerun_channel_entry_name(entry), sizeof(result->channel_str) - 1);
+	result->channel_str[sizeof(result->channel_str) - 1] = 0;
 
 	while (1) {
-		entry = channelscan_advance_channel_internal(scan, entry);
+		entry = hdhomerun_channel_list_prev(scan->channel_list, entry);
 		if (!entry) {
 			scan->next_channel = NULL;
 			break;
@@ -203,7 +236,6 @@ int channelscan_advance(struct hdhomerun
 
 		char *ptr = strchr(result->channel_str, 0);
 		sprintf(ptr, ", %s", hdhomerun_channel_entry_name(entry));
-		result->channel_map |= hdhomerun_channel_entry_channel_map(entry);
 	}
 
 	return 1;
@@ -222,17 +254,6 @@ int channelscan_detect(struct hdhomerun_
 		return 1;
 	}
 
-	/* Refine channel map. */
-	if ((scan->options & HDHOMERUN_CHANNELSCAN_OPTION_REFINE_CHANNEL_MAP) && (result->status.symbol_error_quality == 100)) {
-		scan->channel_map = result->channel_map;
-
-		/* Fixup next channel. */
-		struct hdhomerun_channel_entry_t *entry = scan->next_channel;
-		if (entry && (hdhomerun_channel_entry_channel_map(entry) & scan->channel_map) == 0) {
-			scan->next_channel = channelscan_advance_channel_internal(scan, entry);
-		}
-	}
-
 	/* Detect programs. */
 	result->program_count = 0;
 
@@ -278,7 +299,7 @@ uint8_t channelscan_get_progress(struct 
 	uint32_t frequency = hdhomerun_channel_entry_frequency(entry);
 
 	while (1) {
-		entry = channelscan_advance_channel_internal(scan, entry);
+		entry = hdhomerun_channel_list_prev(scan->channel_list, entry);
 		if (!entry) {
 			break;
 		}
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_channelscan.h myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_channelscan.h
--- mythtv/libs/libmythhdhomerun/hdhomerun_channelscan.h	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/hdhomerun_channelscan.h	2009-06-27 10:32:15.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * hdhomerun_channelscan.h
  *
- * Copyright © 2007-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
+ * Copyright Â© 2007-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
  * This library is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public
@@ -15,21 +15,39 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #define HDHOMERUN_CHANNELSCAN_PROGRAM_NORMAL 0
 #define HDHOMERUN_CHANNELSCAN_PROGRAM_NODATA 1
 #define HDHOMERUN_CHANNELSCAN_PROGRAM_CONTROL 2
 #define HDHOMERUN_CHANNELSCAN_PROGRAM_ENCRYPTED 3
 
-#define HDHOMERUN_CHANNELSCAN_OPTION_REVERSE (1 << 0)
-#define HDHOMERUN_CHANNELSCAN_OPTION_REFINE_CHANNEL_MAP (1 << 1)
-
 struct hdhomerun_channelscan_t;
 
-extern LIBTYPE struct hdhomerun_channelscan_t *channelscan_create(struct hdhomerun_device_t *hd, uint32_t channel_map, uint32_t options);
+extern LIBTYPE struct hdhomerun_channelscan_t *channelscan_create(struct hdhomerun_device_t *hd, const char *channelmap);
 extern LIBTYPE void channelscan_destroy(struct hdhomerun_channelscan_t *scan);
 
 extern LIBTYPE int channelscan_advance(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result);
 extern LIBTYPE int channelscan_detect(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result);
 extern LIBTYPE uint8_t channelscan_get_progress(struct hdhomerun_channelscan_t *scan);
+
+#ifdef __cplusplus
+}
+#endif
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_config.c myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_config.c
--- mythtv/libs/libmythhdhomerun/hdhomerun_config.c	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/hdhomerun_config.c	2009-06-27 10:32:15.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * hdhomerun_config.c
  *
- * Copyright © 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
+ * Copyright Â© 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
  * This library is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public
@@ -15,10 +15,33 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 
 #include "hdhomerun.h"
 
+/*
+ * The console output format should be set to UTF-8, however in XP and Vista this breaks batch file processing.
+ * Attempting to restore on exit fails to restore if the program is terminated by the user.
+ * Solution - set the output format each printf.
+ */
+#if defined(__WINDOWS__)
+#define printf console_printf
+#define vprintf console_vprintf
+#endif
+
 static const char *appname;
 
 struct hdhomerun_device_t *hd;
@@ -131,7 +154,7 @@ static int cmd_get(const char *item)
 	return 1;
 }
 
-static int cmd_set(const char *item, const char *value)
+static int cmd_set_internal(const char *item, const char *value)
 {
 	char *ret_error;
 	if (hdhomerun_device_set_var(hd, item, value, NULL, &ret_error) < 0) {
@@ -147,6 +170,38 @@ static int cmd_set(const char *item, con
 	return 1;
 }
 
+static int cmd_set(const char *item, const char *value)
+{
+	if (strcmp(value, "-") == 0) {
+		char *buffer = NULL;
+		size_t pos = 0;
+
+		while (1) {
+			buffer = (char *)realloc(buffer, pos + 1024);
+			if (!buffer) {
+				fprintf(stderr, "out of memory\n");
+				return -1;
+			}
+
+			int size = fread(buffer + pos, 1, 1024, stdin);
+			pos += size;
+
+			if (size < 1024) {
+				break;
+			}
+		}
+
+		buffer[pos] = 0;
+
+		int ret = cmd_set_internal(item, buffer);
+
+		free(buffer);
+		return ret;
+	}
+
+	return cmd_set_internal(item, value);
+}
+
 static void cmd_scan_printf(FILE *fp, const char *fmt, ...)
 {
 	va_list ap;
@@ -175,13 +230,19 @@ static int cmd_scan(const char *tuner_st
 		return -1;
 	}
 
-	uint32_t channel_map = hdhomerun_device_model_channel_map_all(hd);
-	if (channel_map == 0) {
-		fprintf(stderr, "failed to detect channel_map set\n");
+	char *channelmap;
+	if (hdhomerun_device_get_tuner_channelmap(hd, &channelmap) <= 0) {
+		fprintf(stderr, "failed to query channelmap from device\n");
 		return -1;
 	}
 
-	if (hdhomerun_device_channelscan_init(hd, channel_map, 0) <= 0) {
+	const char *channelmap_scan_group = hdhomerun_channelmap_get_channelmap_scan_group(channelmap);
+	if (!channelmap_scan_group) {
+		fprintf(stderr, "unknown channelmap '%s'\n", channelmap);
+		return -1;
+	}
+
+	if (hdhomerun_device_channelscan_init(hd, channelmap_scan_group) <= 0) {
 		fprintf(stderr, "failed to initialize channel scan\n");
 		return -1;
 	}
@@ -238,6 +299,7 @@ static void cmd_save_abort(int junk)
 	struct hdhomerun_video_stats_t stats;
 	hdhomerun_device_get_video_stats(hd, &stats);
 	hdhomerun_device_stream_stop(hd);
+	hdhomerun_device_destroy(hd);
 
 	fprintf(stderr, "\n");
 	fprintf(stderr, "-- Video statistics --\n");
@@ -257,29 +319,28 @@ static int cmd_save(const char *tuner_st
 		return -1;
 	}
 
-	FILE *fp = NULL;
-
-	if (strcmp(filename, "-") == 0) {
+	FILE *fp;
+	if (strcmp(filename, "null") == 0) {
+		fp = NULL;
+	} else if (strcmp(filename, "-") == 0) {
 		fp = stdout;
-	} else if (strcmp(filename, "null") != 0) {
+	} else {
 		fp = fopen(filename, "wb");
-
 		if (!fp) {
 			fprintf(stderr, "unable to create file %s\n", filename);
 			return -1;
 		}
 	}
 
-	signal(SIGINT, cmd_save_abort);
-	signal(SIGPIPE, cmd_save_abort);
-
 	int ret = hdhomerun_device_stream_start(hd);
 	if (ret <= 0) {
 		fprintf(stderr, "unable to start stream\n");
-		fclose(fp);
 		return ret;
 	}
 
+	signal(SIGINT, cmd_save_abort);
+	signal(SIGPIPE, cmd_save_abort);
+
 	struct hdhomerun_video_stats_t stats_old, stats_cur;
 	hdhomerun_device_get_video_stats(hd, &stats_old);
 
@@ -294,7 +355,10 @@ static int cmd_save(const char *tuner_st
 		}
 
 		if (fp) {
-			fwrite(ptr, 1, actual_size, fp);
+			if (fwrite(ptr, 1, actual_size, fp) != actual_size) {
+				fprintf(stderr, "error writing output\n");
+				return -1;
+			}
 		}
 
 		uint64_t current_time = getcurrenttime();
@@ -413,6 +477,7 @@ static int main_cmd(int argc, char *argv
 static int main_internal(int argc, char *argv[])
 {
 #if defined(__WINDOWS__)
+	/* Initialize network socket support. */
 	WORD wVersionRequested = MAKEWORD(2, 0);
 	WSADATA wsaData;
 	WSAStartup(wVersionRequested, &wsaData);
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_control.c myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_control.c
--- mythtv/libs/libmythhdhomerun/hdhomerun_control.c	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/hdhomerun_control.c	2009-06-27 10:33:25.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * hdhomerun_control.c
  *
- * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
+ * Copyright Â© 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
  * This library is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public
@@ -15,6 +15,19 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 
 #include "hdhomerun.h"
@@ -276,7 +289,7 @@ int hdhomerun_control_send_recv(struct h
 	return hdhomerun_control_send_recv_internal(cs, tx_pkt, rx_pkt, type, HDHOMERUN_CONTROL_RECV_TIMEOUT);
 }
 
-static int hdhomerun_control_get_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, char **pvalue, char **perror)
+static int hdhomerun_control_get_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, uint32_t lockkey, char **pvalue, char **perror)
 {
 	struct hdhomerun_pkt_t *tx_pkt = &cs->tx_pkt;
 	struct hdhomerun_pkt_t *rx_pkt = &cs->rx_pkt;
@@ -285,17 +298,32 @@ static int hdhomerun_control_get_set(str
 	hdhomerun_pkt_reset(tx_pkt);
 
 	int name_len = (int)strlen(name) + 1;
+	if (tx_pkt->end + 3 + name_len > tx_pkt->limit) {
+		return -1;
+	}
 	hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_GETSET_NAME);
 	hdhomerun_pkt_write_var_length(tx_pkt, name_len);
 	hdhomerun_pkt_write_mem(tx_pkt, (const void *)name, name_len);
 
 	if (value) {
 		int value_len = (int)strlen(value) + 1;
+		if (tx_pkt->end + 3 + value_len > tx_pkt->limit) {
+			return -1;
+		}
 		hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_GETSET_VALUE);
 		hdhomerun_pkt_write_var_length(tx_pkt, value_len);
 		hdhomerun_pkt_write_mem(tx_pkt, (const void *)value, value_len);
 	}
 
+	if (lockkey != 0) {
+		if (tx_pkt->end + 6 > tx_pkt->limit) {
+			return -1;
+		}
+		hdhomerun_pkt_write_u8(tx_pkt, HDHOMERUN_TAG_GETSET_LOCKKEY);
+		hdhomerun_pkt_write_var_length(tx_pkt, 4);
+		hdhomerun_pkt_write_u32(tx_pkt, lockkey);
+	}
+
 	/* Send/Recv. */
 	if (hdhomerun_control_send_recv_internal(cs, tx_pkt, rx_pkt, HDHOMERUN_TYPE_GETSET_REQ, HDHOMERUN_CONTROL_RECV_TIMEOUT) < 0) {
 		return -1;
@@ -341,12 +369,17 @@ static int hdhomerun_control_get_set(str
 
 int hdhomerun_control_get(struct hdhomerun_control_sock_t *cs, const char *name, char **pvalue, char **perror)
 {
-	return hdhomerun_control_get_set(cs, name, NULL, pvalue, perror);
+	return hdhomerun_control_get_set(cs, name, NULL, 0, pvalue, perror);
 }
 
 int hdhomerun_control_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, char **pvalue, char **perror)
 {
-	return hdhomerun_control_get_set(cs, name, value, pvalue, perror);
+	return hdhomerun_control_get_set(cs, name, value, 0, pvalue, perror);
+}
+
+int hdhomerun_control_set_with_lockkey(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, uint32_t lockkey, char **pvalue, char **perror)
+{
+	return hdhomerun_control_get_set(cs, name, value, lockkey, pvalue, perror);
 }
 
 int hdhomerun_control_upgrade(struct hdhomerun_control_sock_t *cs, FILE *upgrade_file)
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_control.h myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_control.h
--- mythtv/libs/libmythhdhomerun/hdhomerun_control.h	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/hdhomerun_control.h	2009-06-27 10:32:15.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * hdhomerun_control.h
  *
- * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
+ * Copyright Â© 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
  * This library is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public
@@ -15,6 +15,19 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 #ifdef __cplusplus
 extern "C" {
@@ -83,6 +96,7 @@ extern LIBTYPE int hdhomerun_control_sen
  */
 extern LIBTYPE int hdhomerun_control_get(struct hdhomerun_control_sock_t *cs, const char *name, char **pvalue, char **perror);
 extern LIBTYPE int hdhomerun_control_set(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, char **pvalue, char **perror);
+extern LIBTYPE int hdhomerun_control_set_with_lockkey(struct hdhomerun_control_sock_t *cs, const char *name, const char *value, uint32_t lockkey, char **pvalue, char **perror);
 
 /*
  * Upload new firmware to the device.
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_debug.c myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_debug.c
--- mythtv/libs/libmythhdhomerun/hdhomerun_debug.c	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/hdhomerun_debug.c	2009-06-27 10:32:15.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * hdhomerun_debug.c
  *
- * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
+ * Copyright Â© 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
  * This library is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public
@@ -15,6 +15,19 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 
 /*
@@ -240,26 +253,59 @@ void hdhomerun_debug_vprintf(struct hdho
 	char *end = message->buffer + sizeof(message->buffer) - 2;
 	*end = 0;
 
-	time_t t = time(NULL);
-	strftime(ptr, end - ptr, "%Y%m%d-%H:%M:%S ", localtime(&t));
-	ptr = strchr(ptr, 0);
+	/*
+	 * Timestamp.
+	 */
+	time_t current_time = time(NULL);
+	ptr += strftime(ptr, end - ptr, "%Y%m%d-%H:%M:%S ", localtime(&current_time));
+	if (ptr > end) {
+		ptr = end;
+	}
 
+	/*
+	 * Debug prefix.
+	 */
 	pthread_mutex_lock(&dbg->print_lock);
 
 	if (dbg->prefix) {
-		snprintf(ptr, end - ptr, "%s ", dbg->prefix);
-		ptr = strchr(ptr, 0);
+		int len = snprintf(ptr, end - ptr, "%s ", dbg->prefix);
+		len = (len <= 0) ? 0 : len;
+		ptr += len;
+		if (ptr > end) {
+			ptr = end;
+		}
 	}
 
 	pthread_mutex_unlock(&dbg->print_lock);
 
-	vsnprintf(ptr, end - ptr, fmt, args);
-
-	ptr = strchr(ptr, 0) - 1;
-	if (*ptr++ != '\n') {
-		strcpy(ptr, "\n");
-	}
-
+	/*
+	 * Message text.
+	 */
+	int len = vsnprintf(ptr, end - ptr, fmt, args);
+	len = (len < 0) ? 0 : len; /* len does not include null */
+	ptr += len;
+	if (ptr > end) {
+		ptr = end;
+	}
+
+	/*
+	 * Force newline.
+	 */
+	if ((ptr[-1] != '\n') && (ptr + 1 <= end)) {
+		*ptr++ = '\n';
+	}
+
+	/*
+	 * Force NULL.
+	 */
+	if (ptr + 1 > end) {
+		ptr = end - 1;
+	}
+	*ptr++ = 0;
+
+	/*
+	 * Enqueue.
+	 */
 	pthread_mutex_lock(&dbg->queue_lock);
 
 	message->prev = NULL;
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_debug.h myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_debug.h
--- mythtv/libs/libmythhdhomerun/hdhomerun_debug.h	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/hdhomerun_debug.h	2009-06-27 10:32:15.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * hdhomerun_debug.h
  *
- * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
+ * Copyright Â© 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
  * This library is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public
@@ -15,6 +15,19 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 
 /*
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_device.c myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_device.c
--- mythtv/libs/libmythhdhomerun/hdhomerun_device.c	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/hdhomerun_device.c	2009-06-27 10:33:25.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * hdhomerun_device.c
  *
- * Copyright © 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
+ * Copyright Â© 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
  * This library is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public
@@ -15,6 +15,19 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 
 #include "hdhomerun.h"
@@ -25,6 +38,7 @@ struct hdhomerun_device_t {
 	struct hdhomerun_debug_t *dbg;
 	struct hdhomerun_channelscan_t *scan;
 	unsigned int tuner;
+	uint32_t lockkey;
 	char name[32];
 	char model[32];
 };
@@ -275,22 +289,39 @@ static uint32_t hdhomerun_device_get_sta
 	return (uint32_t)value;
 }
 
+static bool_t hdhomerun_device_get_tuner_status_lock_is_bcast(struct hdhomerun_tuner_status_t *status)
+{
+	if (strcmp(status->lock_str, "8vsb") == 0) {
+		return TRUE;
+	}
+	if (strncmp(status->lock_str, "t8", 2) == 0) {
+		return TRUE;
+	}
+	if (strncmp(status->lock_str, "t7", 2) == 0) {
+		return TRUE;
+	}
+	if (strncmp(status->lock_str, "t6", 2) == 0) {
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
 uint32_t hdhomerun_device_get_tuner_status_ss_color(struct hdhomerun_tuner_status_t *status)
 {
 	unsigned int ss_yellow_min;
 	unsigned int ss_green_min;
 
-	if (strstr(status->lock_str, "8vsb")) {
+	if (!status->lock_supported) {
+		return HDHOMERUN_STATUS_COLOR_NEUTRAL;
+	}
+
+	if (hdhomerun_device_get_tuner_status_lock_is_bcast(status)) {
 		ss_yellow_min = 50;	/* -30dBmV */
 		ss_green_min = 75;	/* -15dBmV */
-	} else if (strstr(status->lock_str, "qam64")) {
-		ss_yellow_min = 80;	/* -12dBmV */
-		ss_green_min = 90;	/* -6dBmV */
-	} else if (strstr(status->lock_str, "qam256")) {
+	} else {
 		ss_yellow_min = 80;	/* -12dBmV */
 		ss_green_min = 90;	/* -6dBmV */
-	} else {
-		return HDHOMERUN_STATUS_COLOR_NEUTRAL;
 	}
 
 	if (status->signal_strength >= ss_green_min) {
@@ -305,10 +336,10 @@ uint32_t hdhomerun_device_get_tuner_stat
 
 uint32_t hdhomerun_device_get_tuner_status_snq_color(struct hdhomerun_tuner_status_t *status)
 {
-	if (status->signal_to_noise_quality >= 60) {
+	if (status->signal_to_noise_quality >= 70) {
 		return HDHOMERUN_STATUS_COLOR_GREEN;
 	}
-	if (status->signal_to_noise_quality >= 40) {
+	if (status->signal_to_noise_quality >= 50) {
 		return HDHOMERUN_STATUS_COLOR_YELLOW;
 	}
 
@@ -461,6 +492,13 @@ int hdhomerun_device_get_tuner_plotsampl
 	return 1;
 }
 
+int hdhomerun_device_get_tuner_lockkey_owner(struct hdhomerun_device_t *hd, char **powner)
+{
+	char name[32];
+	sprintf(name, "/tuner%u/lockkey", hd->tuner);
+	return hdhomerun_control_get(hd->cs, name, powner, NULL);
+}
+
 int hdhomerun_device_get_ir_target(struct hdhomerun_device_t *hd, char **ptarget)
 {
 	return hdhomerun_control_get(hd->cs, "/ir/target", ptarget, NULL);
@@ -499,21 +537,21 @@ int hdhomerun_device_set_tuner_channel(s
 {
 	char name[32];
 	sprintf(name, "/tuner%u/channel", hd->tuner);
-	return hdhomerun_control_set(hd->cs, name, channel, NULL, NULL);
+	return hdhomerun_control_set_with_lockkey(hd->cs, name, channel, hd->lockkey, NULL, NULL);
 }
 
 int hdhomerun_device_set_tuner_channelmap(struct hdhomerun_device_t *hd, const char *channelmap)
 {
 	char name[32];
 	sprintf(name, "/tuner%u/channelmap", hd->tuner);
-	return hdhomerun_control_set(hd->cs, name, channelmap, NULL, NULL);
+	return hdhomerun_control_set_with_lockkey(hd->cs, name, channelmap, hd->lockkey, NULL, NULL);
 }
 
 int hdhomerun_device_set_tuner_filter(struct hdhomerun_device_t *hd, const char *filter)
 {
 	char name[32];
 	sprintf(name, "/tuner%u/filter", hd->tuner);
-	return hdhomerun_control_set(hd->cs, name, filter, NULL, NULL);
+	return hdhomerun_control_set_with_lockkey(hd->cs, name, filter, hd->lockkey, NULL, NULL);
 }
 
 static int hdhomerun_device_set_tuner_filter_by_array_append(char **pptr, char *end, uint16_t range_begin, uint16_t range_end)
@@ -578,8 +616,8 @@ int hdhomerun_device_set_tuner_filter_by
 	/* Remove trailing space. */
 	if (ptr > filter) {
 		ptr--;
-		*ptr = 0;
 	}
+	*ptr = 0;
 
 	return hdhomerun_device_set_tuner_filter(hd, filter);
 }
@@ -588,14 +626,14 @@ int hdhomerun_device_set_tuner_program(s
 {
 	char name[32];
 	sprintf(name, "/tuner%u/program", hd->tuner);
-	return hdhomerun_control_set(hd->cs, name, program, NULL, NULL);
+	return hdhomerun_control_set_with_lockkey(hd->cs, name, program, hd->lockkey, NULL, NULL);
 }
 
 int hdhomerun_device_set_tuner_target(struct hdhomerun_device_t *hd, const char *target)
 {
 	char name[32];
 	sprintf(name, "/tuner%u/target", hd->tuner);
-	return hdhomerun_control_set(hd->cs, name, target, NULL, NULL);
+	return hdhomerun_control_set_with_lockkey(hd->cs, name, target, hd->lockkey, NULL, NULL);
 }
 
 int hdhomerun_device_set_tuner_target_to_local_protocol(struct hdhomerun_device_t *hd, const char *protocol)
@@ -645,6 +683,40 @@ int hdhomerun_device_set_var(struct hdho
 	return hdhomerun_control_set(hd->cs, name, value, pvalue, perror);
 }
 
+int hdhomerun_device_tuner_lockkey_request(struct hdhomerun_device_t *hd)
+{
+	uint32_t new_lockkey = (uint32_t)getcurrenttime();
+
+	char name[32];
+	sprintf(name, "/tuner%u/lockkey", hd->tuner);
+
+	char new_lockkey_str[64];
+	sprintf(new_lockkey_str, "%u", (unsigned int)new_lockkey);
+
+	int ret = hdhomerun_control_set_with_lockkey(hd->cs, name, new_lockkey_str, hd->lockkey, NULL, NULL);
+	if (ret <= 0) {
+		hd->lockkey = 0;
+		return ret;
+	}
+
+	hd->lockkey = new_lockkey;
+	return ret;
+}
+
+int hdhomerun_device_tuner_lockkey_release(struct hdhomerun_device_t *hd)
+{
+	if (hd->lockkey == 0) {
+		return 1;
+	}
+
+	char name[32];
+	sprintf(name, "/tuner%u/lockkey", hd->tuner);
+	int ret = hdhomerun_control_set_with_lockkey(hd->cs, name, "none", hd->lockkey, NULL, NULL);
+
+	hd->lockkey = 0;
+	return ret;
+}
+
 int hdhomerun_device_wait_for_lock(struct hdhomerun_device_t *hd, struct hdhomerun_tuner_status_t *status)
 {
 	/* Wait for up to 2.5 seconds for lock. */
@@ -708,13 +780,13 @@ void hdhomerun_device_stream_stop(struct
 	hdhomerun_device_set_tuner_target(hd, "none");
 }
 
-int hdhomerun_device_channelscan_init(struct hdhomerun_device_t *hd, uint32_t channel_map, uint32_t options)
+int hdhomerun_device_channelscan_init(struct hdhomerun_device_t *hd, const char *channelmap)
 {
 	if (hd->scan) {
 		channelscan_destroy(hd->scan);
 	}
 
-	hd->scan = channelscan_create(hd, channel_map, options);
+	hd->scan = channelscan_create(hd, channelmap);
 	if (!hd->scan) {
 		return -1;
 	}
@@ -787,55 +859,23 @@ const char *hdhomerun_device_get_model_s
 		return NULL;
 	}
 	if (ret == 0) {
-		strcpy(hd->model, "hdhomerun_atsc");
-		return hd->model;
+		model_str = "hdhomerun_atsc";
 	}
 
-	strcpy(hd->model, model_str);
-	return hd->model;
-}
+	strncpy(hd->model, model_str, sizeof(hd->model) - 1);
+	hd->model[sizeof(hd->model) - 1] = 0;
 
-uint32_t hdhomerun_device_model_channel_map_all(struct hdhomerun_device_t *hd)
-{
-	return hdhomerun_device_model_channel_map_antenna(hd) | hdhomerun_device_model_channel_map_cable(hd);
-}
-
-uint32_t hdhomerun_device_model_channel_map_antenna(struct hdhomerun_device_t *hd)
-{
-	const char *model = hdhomerun_device_get_model_str(hd);
-	if (!model) {
-		return 0;
-	}
-
-	if (strstr(model, "atsc")) {
-		return CHANNEL_MAP_US_BCAST;
-	}
-
-	if (strstr(model, "dvbt")) {
-		return CHANNEL_MAP_UK_BCAST | CHANNEL_MAP_NZ_BCAST;
-	}
-
-	return 0;
-}
-
-uint32_t hdhomerun_device_model_channel_map_cable(struct hdhomerun_device_t *hd)
-{
-	const char *model = hdhomerun_device_get_model_str(hd);
-	if (!model) {
-		return 0;
-	}
-
-	if (strstr(model, "atsc")) {
-		return CHANNEL_MAP_US_CABLE | CHANNEL_MAP_US_HRC | CHANNEL_MAP_US_IRC;
-	}
-
-	return 0;
+	return hd->model;
 }
 
 int hdhomerun_device_upgrade(struct hdhomerun_device_t *hd, FILE *upgrade_file)
 {
+	hdhomerun_control_set(hd->cs, "/tuner0/lockkey", "force", NULL, NULL);
 	hdhomerun_control_set(hd->cs, "/tuner0/channel", "none", NULL, NULL);
+
+	hdhomerun_control_set(hd->cs, "/tuner1/lockkey", "force", NULL, NULL);
 	hdhomerun_control_set(hd->cs, "/tuner1/channel", "none", NULL, NULL);
+
 	return hdhomerun_control_upgrade(hd->cs, upgrade_file);
 }
 
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_device.h myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_device.h
--- mythtv/libs/libmythhdhomerun/hdhomerun_device.h	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/hdhomerun_device.h	2009-06-27 10:33:25.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * hdhomerun_device.h
  *
- * Copyright © 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
+ * Copyright Â© 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
  * This library is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public
@@ -15,6 +15,19 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 
 #ifdef __cplusplus
@@ -28,7 +41,7 @@ extern "C" {
 #define HDHOMERUN_STATUS_COLOR_NEUTRAL	0xFFFFFFFF
 #define HDHOMERUN_STATUS_COLOR_RED		0xFFFF0000
 #define HDHOMERUN_STATUS_COLOR_YELLOW	0xFFFFFF00
-#define HDHOMERUN_STATUS_COLOR_GREEN	0xFF008000
+#define HDHOMERUN_STATUS_COLOR_GREEN	0xFF00C000
 
 #define HDHOMERUN_TARGET_PROTOCOL_UDP "udp"
 #define HDHOMERUN_TARGET_PROTOCOL_RTP "rtp"
@@ -112,6 +125,7 @@ extern LIBTYPE int hdhomerun_device_get_
 extern LIBTYPE int hdhomerun_device_get_tuner_program(struct hdhomerun_device_t *hd, char **pprogram);
 extern LIBTYPE int hdhomerun_device_get_tuner_target(struct hdhomerun_device_t *hd, char **ptarget);
 extern LIBTYPE int hdhomerun_device_get_tuner_plotsample(struct hdhomerun_device_t *hd, struct hdhomerun_plotsample_t **psamples, size_t *pcount);
+extern LIBTYPE int hdhomerun_device_get_tuner_lockkey_owner(struct hdhomerun_device_t *hd, char **powner);
 extern LIBTYPE int hdhomerun_device_get_ir_target(struct hdhomerun_device_t *hd, char **ptarget);
 extern LIBTYPE int hdhomerun_device_get_lineup_location(struct hdhomerun_device_t *hd, char **plocation);
 extern LIBTYPE int hdhomerun_device_get_version(struct hdhomerun_device_t *hd, char **pversion_str, uint32_t *pversion_num);
@@ -121,9 +135,6 @@ extern LIBTYPE uint32_t hdhomerun_device
 extern LIBTYPE uint32_t hdhomerun_device_get_tuner_status_seq_color(struct hdhomerun_tuner_status_t *status);
 
 extern LIBTYPE const char *hdhomerun_device_get_model_str(struct hdhomerun_device_t *hd);
-extern LIBTYPE uint32_t hdhomerun_device_model_channel_map_all(struct hdhomerun_device_t *hd);
-extern LIBTYPE uint32_t hdhomerun_device_model_channel_map_antenna(struct hdhomerun_device_t *hd);
-extern LIBTYPE uint32_t hdhomerun_device_model_channel_map_cable(struct hdhomerun_device_t *hd);
 
 /*
  * Set operations.
@@ -166,6 +177,22 @@ extern LIBTYPE int hdhomerun_device_get_
 extern LIBTYPE int hdhomerun_device_set_var(struct hdhomerun_device_t *hd, const char *name, const char *value, char **pvalue, char **perror);
 
 /*
+ * Tuner locking.
+ *
+ * The hdhomerun_device_tuner_lockkey_request function is used to obtain a lock
+ * or to verify that the hdhomerun_device object still holds the lock.
+ * Returns 1 if the lock request was successful and the lock was obtained.
+ * Returns 0 if the lock request was rejected.
+ * Returns -1 if a communication error occurs.
+ *
+ * The hdhomerun_device_tuner_lockkey_release function is used to release a
+ * previously held lock. If locking is used then this function must be called
+ * before destroying the hdhomerun_device object.
+ */
+extern LIBTYPE int hdhomerun_device_tuner_lockkey_request(struct hdhomerun_device_t *hd);
+extern LIBTYPE int hdhomerun_device_tuner_lockkey_release(struct hdhomerun_device_t *hd);
+
+/*
  * Wait for tuner lock after channel change.
  *
  * The hdhomerun_device_wait_for_lock function is used to detect/wait for a lock vs no lock indication
@@ -202,7 +229,7 @@ extern LIBTYPE void hdhomerun_device_str
 /*
  * Channel scan API.
  */
-extern LIBTYPE int hdhomerun_device_channelscan_init(struct hdhomerun_device_t *hd, uint32_t channel_map, uint32_t options);
+extern LIBTYPE int hdhomerun_device_channelscan_init(struct hdhomerun_device_t *hd, const char *channelmap);
 extern LIBTYPE int hdhomerun_device_channelscan_advance(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result);
 extern LIBTYPE int hdhomerun_device_channelscan_detect(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result);
 extern LIBTYPE uint8_t hdhomerun_device_channelscan_get_progress(struct hdhomerun_device_t *hd);
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_dhcp.c myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_dhcp.c
--- mythtv/libs/libmythhdhomerun/hdhomerun_dhcp.c	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/hdhomerun_dhcp.c	2009-06-27 10:32:15.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * hdhomerun_dhcp.c
  *
- * Copyright © 2006-2007 Silicondust Engineering Ltd. <www.silicondust.com>.
+ * Copyright Â© 2006-2007 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
  * This library is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public
@@ -15,6 +15,19 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 
 #include "hdhomerun.h"
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_dhcp.h myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_dhcp.h
--- mythtv/libs/libmythhdhomerun/hdhomerun_dhcp.h	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/hdhomerun_dhcp.h	2009-06-27 10:32:15.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * hdhomerun_dhcp.h
  *
- * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
+ * Copyright Â© 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
  * This library is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public
@@ -15,6 +15,19 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 
 #ifdef __cplusplus
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_discover.c myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_discover.c
--- mythtv/libs/libmythhdhomerun/hdhomerun_discover.c	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/hdhomerun_discover.c	2009-06-27 10:32:15.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * hdhomerun_discover.c
  *
- * Copyright © 2006-2007 Silicondust Engineering Ltd. <www.silicondust.com>.
+ * Copyright Â© 2006-2007 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
  * This library is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public
@@ -15,6 +15,19 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 
 #include "hdhomerun.h"
@@ -23,21 +36,20 @@
 #include <windows.h>
 #include <iphlpapi.h>
 #define USE_IPHLPAPI 1
+#else
+#include <net/if.h>
+#include <sys/ioctl.h>
+#ifndef _SIZEOF_ADDR_IFREQ
+#define _SIZEOF_ADDR_IFREQ(x) sizeof(x)
 #endif
-
-#include <sys/param.h>  // Defines BSD on FreeBSD and Mac OS X
-
-#if defined(__linux__) || defined(__APPLE__) || defined(BSD)
-#include <ifaddrs.h>
-#define USE_IFADDRS 1
-#include <sys/select.h>
 #endif
 
 #define HDHOMERUN_DISOCVER_MAX_SOCK_COUNT 16
 
 struct hdhomerun_discover_sock_t {
 	int sock;
-	uint32_t broadcast_ip;
+	uint32_t local_ip;
+	uint32_t subnet_mask;
 };
 
 struct hdhomerun_discover_t {
@@ -47,16 +59,16 @@ struct hdhomerun_discover_t {
 	struct hdhomerun_pkt_t rx_pkt;
 };
 
-static void hdhomerun_discover_sock_create(struct hdhomerun_discover_t *ds, uint32_t local_ip, uint32_t mask)
+static bool_t hdhomerun_discover_sock_create(struct hdhomerun_discover_t *ds, uint32_t local_ip, uint32_t subnet_mask)
 {
 	if (ds->sock_count >= HDHOMERUN_DISOCVER_MAX_SOCK_COUNT) {
-		return;
+		return FALSE;
 	}
 
 	/* Create socket. */
 	int sock = (int)socket(AF_INET, SOCK_DGRAM, 0);
 	if (sock == -1) {
-		return;
+		return FALSE;
 	}
 
 	/* Set timeouts. */
@@ -75,13 +87,16 @@ static void hdhomerun_discover_sock_crea
 	sock_addr.sin_port = htons(0);
 	if (bind(sock, (struct sockaddr *)&sock_addr, sizeof(sock_addr)) != 0) {
 		close(sock);
-		return;
+		return FALSE;
 	}
 
 	/* Write sock entry. */
 	struct hdhomerun_discover_sock_t *dss = &ds->socks[ds->sock_count++];
 	dss->sock = sock;
-	dss->broadcast_ip = local_ip | ~mask;
+	dss->local_ip = local_ip;
+	dss->subnet_mask = subnet_mask;
+
+	return TRUE;
 }
 
 #if defined(USE_IPHLPAPI)
@@ -125,45 +140,52 @@ static void hdhomerun_discover_sock_dete
 
 	free(pAdapterInfo);
 }
-#endif
 
-#if defined(USE_IFADDRS)
+#else
+
 static void hdhomerun_discover_sock_detect(struct hdhomerun_discover_t *ds)
 {
-	struct ifaddrs *ifap;
-	if (getifaddrs(&ifap) < 0) {
+	int fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (fd == -1) {
+		return;
+	}
+
+	struct ifconf ifc;
+	uint8_t buf[8192];
+	ifc.ifc_len = sizeof(buf);
+	ifc.ifc_buf = (char *)buf;
+
+	memset(buf, 0, sizeof(buf));
+
+	if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) {
+		close(fd);
 		return;
 	}
 
-	struct ifaddrs *p = ifap;
-	while (p) {
-		struct sockaddr_in *addr_in = (struct sockaddr_in *)p->ifa_addr;
-		struct sockaddr_in *mask_in = (struct sockaddr_in *)p->ifa_netmask;
-		if (!addr_in || !mask_in) {
-			p = p->ifa_next;
+	uint8_t *ptr = (uint8_t *)ifc.ifc_req;
+	uint8_t	*end = (uint8_t *)&ifc.ifc_buf[ifc.ifc_len];
+
+	while (ptr <= end) {
+		struct ifreq *ifr = (struct ifreq *)ptr;
+		ptr += _SIZEOF_ADDR_IFREQ(*ifr);
+
+		if (ioctl(fd, SIOCGIFADDR, ifr) != 0) {
 			continue;
 		}
-
+		struct sockaddr_in *addr_in = (struct sockaddr_in *)&(ifr->ifr_addr);
 		uint32_t local_ip = ntohl(addr_in->sin_addr.s_addr);
-		uint32_t mask = ntohl(mask_in->sin_addr.s_addr);
 		if (local_ip == 0) {
-			p = p->ifa_next;
 			continue;
 		}
 
+		if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) {
+			continue;
+		}
+		struct sockaddr_in *mask_in = (struct sockaddr_in *)&(ifr->ifr_addr);
+		uint32_t mask = ntohl(mask_in->sin_addr.s_addr);
+
 		hdhomerun_discover_sock_create(ds, local_ip, mask);
-		p = p->ifa_next;
 	}
-
-	freeifaddrs(ifap);
-}
-#endif
-
-
-#if !defined(USE_IPHLPAPI) && !defined(USE_IFADDRS)
-static void hdhomerun_discover_sock_detect(struct hdhomerun_discover_t *ds)
-{
-	/* do nothing */
 }
 #endif
 
@@ -174,16 +196,15 @@ static struct hdhomerun_discover_t *hdho
 		return NULL;
 	}
 
-	/* Detect & create sockets. */
-	hdhomerun_discover_sock_detect(ds);
-	if (ds->sock_count == 0) {
-		hdhomerun_discover_sock_create(ds, 0, 0);
-		if (ds->sock_count == 0) {
-			free(ds);
-			return NULL;
-		}
+	/* Create a routable socket. */
+	if (!hdhomerun_discover_sock_create(ds, 0, 0)) {
+		free(ds);
+		return NULL;
 	}
 
+	/* Detect & create local sockets. */
+	hdhomerun_discover_sock_detect(ds);
+
 	/* Success. */
 	return ds;
 }
@@ -201,10 +222,6 @@ static void hdhomerun_discover_destroy(s
 
 static bool_t hdhomerun_discover_send_internal(struct hdhomerun_discover_t *ds, struct hdhomerun_discover_sock_t *dss, uint32_t target_ip, uint32_t device_type, uint32_t device_id)
 {
-	if (target_ip == 0) {
-		target_ip = dss->broadcast_ip;
-	}
-
 	struct hdhomerun_pkt_t *tx_pkt = &ds->tx_pkt;
 	hdhomerun_pkt_reset(tx_pkt);
 
@@ -230,19 +247,70 @@ static bool_t hdhomerun_discover_send_in
 	return TRUE;
 }
 
-static bool_t hdhomerun_discover_send(struct hdhomerun_discover_t *ds, uint32_t target_ip, uint32_t device_type, uint32_t device_id)
+static bool_t hdhomerun_discover_send_wildcard_ip(struct hdhomerun_discover_t *ds, uint32_t device_type, uint32_t device_id)
 {
 	bool_t result = FALSE;
 
+	/*
+	 * Send subnet broadcast using each local ip socket.
+	 * This will work with multiple separate 169.254.x.x interfaces.
+	 */
 	unsigned int i;
-	for (i = 0; i < ds->sock_count; i++) {
+	for (i = 1; i < ds->sock_count; i++) {
+		struct hdhomerun_discover_sock_t *dss = &ds->socks[i];
+		uint32_t target_ip = dss->local_ip | ~dss->subnet_mask;
+		result |= hdhomerun_discover_send_internal(ds, dss, target_ip, device_type, device_id);
+	}
+
+	/*
+	 * If no local ip sockets then fall back to sending a global broadcast letting the OS choose the interface.
+	 */
+	if (!result) {
+		struct hdhomerun_discover_sock_t *dss = &ds->socks[0];
+		result = hdhomerun_discover_send_internal(ds, dss, 0xFFFFFFFF, device_type, device_id);
+	}
+
+	return result;
+}
+
+static bool_t hdhomerun_discover_send_target_ip(struct hdhomerun_discover_t *ds, uint32_t target_ip, uint32_t device_type, uint32_t device_id)
+{
+	bool_t result = FALSE;
+
+	/*
+	 * Send targeted packet from any local ip that is in the same subnet.
+	 * This will work with multiple separate 169.254.x.x interfaces.
+	 */
+	unsigned int i;
+	for (i = 1; i < ds->sock_count; i++) {
 		struct hdhomerun_discover_sock_t *dss = &ds->socks[i];
+		if ((target_ip & dss->subnet_mask) != (dss->local_ip & dss->subnet_mask)) {
+			continue;
+		}
+
 		result |= hdhomerun_discover_send_internal(ds, dss, target_ip, device_type, device_id);
 	}
 
+	/*
+	 * If target IP does not match a local subnet then fall back to letting the OS choose the gateway interface.
+	 */
+	if (!result) {
+		struct hdhomerun_discover_sock_t *dss = &ds->socks[0];
+		result = hdhomerun_discover_send_internal(ds, dss, target_ip, device_type, device_id);
+	}
+
 	return result;
 }
 
+static bool_t hdhomerun_discover_send(struct hdhomerun_discover_t *ds, uint32_t target_ip, uint32_t device_type, uint32_t device_id)
+{
+	if (target_ip != 0) {
+		return hdhomerun_discover_send_target_ip(ds, target_ip, device_type, device_id);
+	}
+
+	return hdhomerun_discover_send_wildcard_ip(ds, device_type, device_id);
+}
+
 static int hdhomerun_discover_recv_internal(struct hdhomerun_discover_t *ds, struct hdhomerun_discover_sock_t *dss, struct hdhomerun_discover_device_t *result)
 {
 	struct hdhomerun_pkt_t *rx_pkt = &ds->rx_pkt;
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_discover.h myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_discover.h
--- mythtv/libs/libmythhdhomerun/hdhomerun_discover.h	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/hdhomerun_discover.h	2009-06-27 10:32:15.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * hdhomerun_discover.h
  *
- * Copyright © 2006-2007 Silicondust Engineering Ltd. <www.silicondust.com>.
+ * Copyright Â© 2006-2007 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
  * This library is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public
@@ -15,6 +15,19 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 #ifdef __cplusplus
 extern "C" {
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_os.h myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_os.h
--- mythtv/libs/libmythhdhomerun/hdhomerun_os.h	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/hdhomerun_os.h	2009-06-27 10:32:15.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * hdhomerun_os.h
  *
- * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
+ * Copyright Â© 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
  * This library is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public
@@ -15,6 +15,19 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 
 #if defined(_WIN32) || defined(_WIN64)
@@ -22,39 +35,9 @@
 #endif
 
 #if defined(__WINDOWS__)
-#define _WINSOCKAPI_
-#include <windows.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <wspiapi.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <signal.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/timeb.h>
-
-#else /* !defined(__WINDOWS__) */
-#define _FILE_OFFSET_BITS 64
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/timeb.h>
-#include <sys/wait.h>
-#include <sys/signal.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <pthread.h>
+#include "hdhomerun_os_windows.h"
+#else
+#include "hdhomerun_os_posix.h"
 #endif
 
 #if !defined(TRUE)
@@ -64,119 +47,3 @@
 #if !defined(FALSE)
 #define FALSE 0
 #endif
-
-#if defined(__WINDOWS__)
-
-#define LIBTYPE
-
-#if defined(DLL_IMPORT)
-#define LIBTYPE __declspec( dllexport )
-#endif
-
-#if defined(DLL_EXPORT)
-#define LIBTYPE __declspec( dllimport )
-#endif
-
-typedef int bool_t;
-typedef signed __int8 int8_t;
-typedef signed __int16 int16_t;
-typedef signed __int32 int32_t;
-typedef signed __int64 int64_t;
-typedef unsigned __int8 uint8_t;
-typedef unsigned __int16 uint16_t;
-typedef unsigned __int32 uint32_t;
-typedef unsigned __int64 uint64_t;
-typedef HANDLE pthread_t;
-typedef HANDLE pthread_mutex_t;
-
-#define socklen_t int
-#define close closesocket
-#define sock_getlasterror WSAGetLastError()
-#define sock_getlasterror_socktimeout (WSAGetLastError() == WSAETIMEDOUT)
-#define va_copy(x, y) x = y
-#define atoll _atoi64
-#define strdup _strdup
-#define strcasecmp _stricmp
-#define snprintf _snprintf
-#define fseeko _fseeki64
-#define ftello _ftelli64
-#define usleep(us) Sleep((us)/1000)
-#define sleep(sec) Sleep((sec)*1000)
-#define THREAD_FUNC_PREFIX DWORD WINAPI
-#define SIGPIPE SIGABRT
-
-static inline uint64_t getcurrenttime(void)
-{
-	struct timeb tb;
-	ftime(&tb);
-	return ((uint64_t)tb.time * 1000) + tb.millitm;
-}
-
-static inline int setsocktimeout(int s, int level, int optname, uint64_t timeout)
-{
-	int t = (int)timeout;
-	return setsockopt(s, level, optname, (char *)&t, sizeof(t));
-}
-
-static inline int pthread_create(pthread_t *tid, void *attr, LPTHREAD_START_ROUTINE start, void *arg)
-{
-	*tid = CreateThread(NULL, 0, start, arg, 0, NULL);
-	if (!*tid) {
-		return (int)GetLastError();
-	}
-	return 0;
-}
-
-static inline int pthread_join(pthread_t tid, void **value_ptr)
-{
-	while (1) {
-		DWORD ExitCode = 0;
-		if (!GetExitCodeThread(tid, &ExitCode)) {
-			return (int)GetLastError();
-		}
-		if (ExitCode != STILL_ACTIVE) {
-			return 0;
-		}
-	}
-}
-
-extern inline void pthread_mutex_init(pthread_mutex_t *mutex, void *attr)
-{
-	*mutex = CreateMutex(NULL, FALSE, NULL);
-}
-
-extern inline void pthread_mutex_lock(pthread_mutex_t *mutex)
-{
-	WaitForSingleObject(*mutex, INFINITE);
-}
-
-extern inline void pthread_mutex_unlock(pthread_mutex_t *mutex)
-{
-	ReleaseMutex(*mutex);
-}
-
-#else /* !defined(__WINDOWS__) */
-
-typedef int bool_t;
-
-#define LIBTYPE
-#define sock_getlasterror errno
-#define sock_getlasterror_socktimeout (errno == EAGAIN)
-#define THREAD_FUNC_PREFIX void *
-
-static inline uint64_t getcurrenttime(void)
-{
-	struct timeval t;
-	gettimeofday(&t, NULL);
-	return ((uint64_t)t.tv_sec * 1000) + (t.tv_usec / 1000);
-}
-
-static inline int setsocktimeout(int s, int level, int optname, uint64_t timeout)
-{
-	struct timeval t;
-	t.tv_sec = timeout / 1000;
-	t.tv_usec = (timeout % 1000) * 1000;
-	return setsockopt(s, level, optname, (char *)&t, sizeof(t));
-}
-
-#endif
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_os_posix.h myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_os_posix.h
--- mythtv/libs/libmythhdhomerun/hdhomerun_os_posix.h	1969-12-31 18:00:00.000000000 -0600
+++ mythtv/libs/libmythhdhomerun/hdhomerun_os_posix.h	2009-06-27 10:32:15.000000000 -0500
@@ -0,0 +1,74 @@
+/*
+ * hdhomerun_os_posix.h
+ *
+ * Copyright Â© 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
+ *
+ * This library is free software; you can redistribute it and/or 
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
+ */
+
+#define _FILE_OFFSET_BITS 64
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/wait.h>
+#include <sys/signal.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <pthread.h>
+
+typedef int bool_t;
+
+#define LIBTYPE
+#define sock_getlasterror errno
+#define sock_getlasterror_socktimeout (errno == EAGAIN)
+#define console_vprintf vprintf
+#define console_printf printf
+#define THREAD_FUNC_PREFIX void *
+
+static inline uint64_t getcurrenttime(void)
+{
+	struct timeval t;
+	gettimeofday(&t, NULL);
+	return ((uint64_t)t.tv_sec * 1000) + (t.tv_usec / 1000);
+}
+
+static inline int setsocktimeout(int s, int level, int optname, uint64_t timeout)
+{
+	struct timeval t;
+	t.tv_sec = timeout / 1000;
+	t.tv_usec = (timeout % 1000) * 1000;
+	return setsockopt(s, level, optname, (char *)&t, sizeof(t));
+}
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_os_windows.h myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_os_windows.h
--- mythtv/libs/libmythhdhomerun/hdhomerun_os_windows.h	1969-12-31 18:00:00.000000000 -0600
+++ mythtv/libs/libmythhdhomerun/hdhomerun_os_windows.h	2009-06-27 10:32:15.000000000 -0500
@@ -0,0 +1,162 @@
+/*
+ * hdhomerun_os_windows.h
+ *
+ * Copyright Â© 2006-2008 Silicondust Engineering Ltd. <www.silicondust.com>.
+ *
+ * This library is free software; you can redistribute it and/or 
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
+ */
+
+#define _WINSOCKAPI_
+#include <windows.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <wspiapi.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <signal.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/timeb.h>
+
+#if defined(DLL_IMPORT)
+#define LIBTYPE __declspec( dllexport )
+#elif  defined(DLL_EXPORT)
+#define LIBTYPE __declspec( dllimport )
+#else
+#define LIBTYPE
+#endif
+
+typedef int bool_t;
+typedef signed __int8 int8_t;
+typedef signed __int16 int16_t;
+typedef signed __int32 int32_t;
+typedef signed __int64 int64_t;
+typedef unsigned __int8 uint8_t;
+typedef unsigned __int16 uint16_t;
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+typedef HANDLE pthread_t;
+typedef HANDLE pthread_mutex_t;
+
+#define socklen_t int
+#define close closesocket
+#define sock_getlasterror WSAGetLastError()
+#define sock_getlasterror_socktimeout (WSAGetLastError() == WSAETIMEDOUT)
+#define va_copy(x, y) x = y
+#define atoll _atoi64
+#define strdup _strdup
+#define strcasecmp _stricmp
+#define snprintf _snprintf
+#define fseeko _fseeki64
+#define ftello _ftelli64
+#define THREAD_FUNC_PREFIX DWORD WINAPI
+#define SIGPIPE SIGABRT
+
+static inline int usleep(unsigned int us)
+{
+	Sleep((us)/1000);
+	return 0;
+}
+
+static inline int sleep(unsigned int sec)
+{
+	Sleep((sec)*1000);
+	return 0;
+}
+
+static inline uint64_t getcurrenttime(void)
+{
+	struct timeb tb;
+	ftime(&tb);
+	return ((uint64_t)tb.time * 1000) + tb.millitm;
+}
+
+static inline int setsocktimeout(int s, int level, int optname, uint64_t timeout)
+{
+	int t = (int)timeout;
+	return setsockopt(s, level, optname, (char *)&t, sizeof(t));
+}
+
+static inline int pthread_create(pthread_t *tid, void *attr, LPTHREAD_START_ROUTINE start, void *arg)
+{
+	*tid = CreateThread(NULL, 0, start, arg, 0, NULL);
+	if (!*tid) {
+		return (int)GetLastError();
+	}
+	return 0;
+}
+
+static inline int pthread_join(pthread_t tid, void **value_ptr)
+{
+	while (1) {
+		DWORD ExitCode = 0;
+		if (!GetExitCodeThread(tid, &ExitCode)) {
+			return (int)GetLastError();
+		}
+		if (ExitCode != STILL_ACTIVE) {
+			return 0;
+		}
+	}
+}
+
+static inline void pthread_mutex_init(pthread_mutex_t *mutex, void *attr)
+{
+	*mutex = CreateMutex(NULL, FALSE, NULL);
+}
+
+static inline void pthread_mutex_lock(pthread_mutex_t *mutex)
+{
+	WaitForSingleObject(*mutex, INFINITE);
+}
+
+static inline void pthread_mutex_unlock(pthread_mutex_t *mutex)
+{
+	ReleaseMutex(*mutex);
+}
+
+/*
+ * The console output format should be set to UTF-8, however in XP and Vista this breaks batch file processing.
+ * Attempting to restore on exit fails to restore if the program is terminated by the user.
+ * Solution - set the output format each printf.
+ */
+static inline void console_vprintf(const char *fmt, va_list ap)
+{
+	UINT cp = GetConsoleOutputCP();
+	SetConsoleOutputCP(CP_UTF8);
+	vprintf(fmt, ap);
+	SetConsoleOutputCP(cp);
+}
+
+static inline void console_printf(const char *fmt, ...)
+{
+	va_list ap;
+	va_start(ap, fmt);
+	console_vprintf(fmt, ap);
+	va_end(ap);
+}
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_pkt.c myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_pkt.c
--- mythtv/libs/libmythhdhomerun/hdhomerun_pkt.c	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/hdhomerun_pkt.c	2009-06-27 10:32:15.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * hdhomerun_pkt.c
  *
- * Copyright © 2005-2006 Silicondust Engineering Ltd. <www.silicondust.com>.
+ * Copyright Â© 2005-2006 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
  * This library is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public
@@ -15,6 +15,19 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 
 #include "hdhomerun.h"
@@ -38,7 +51,7 @@ void hdhomerun_pkt_destroy(struct hdhome
 
 void hdhomerun_pkt_reset(struct hdhomerun_pkt_t *pkt)
 {
-	pkt->limit = pkt->buffer + sizeof(pkt->buffer);
+	pkt->limit = pkt->buffer + sizeof(pkt->buffer) - 4;
 	pkt->start = pkt->buffer + 1024;
 	pkt->end = pkt->start;
 	pkt->pos = pkt->start;
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_pkt.h myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_pkt.h
--- mythtv/libs/libmythhdhomerun/hdhomerun_pkt.h	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/hdhomerun_pkt.h	2009-06-27 10:32:15.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * hdhomerun_pkt.h
  *
- * Copyright © 2005-2006 Silicondust Engineering Ltd. <www.silicondust.com>.
+ * Copyright Â© 2005-2006 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
  * This library is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public
@@ -15,6 +15,19 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 #ifdef __cplusplus
 extern "C" {
@@ -109,6 +122,9 @@ extern "C" {
 #define HDHOMERUN_DISCOVER_UDP_PORT 65001
 #define HDHOMERUN_CONTROL_TCP_PORT 65001
 
+#define HDHOMERUN_MAX_PACKET_SIZE 1460
+#define HDHOMERUN_MAX_PAYLOAD_SIZE 1452
+
 #define HDHOMERUN_TYPE_DISCOVER_REQ 0x0002
 #define HDHOMERUN_TYPE_DISCOVER_RPY 0x0003
 #define HDHOMERUN_TYPE_GETSET_REQ 0x0004
@@ -120,6 +136,7 @@ extern "C" {
 #define HDHOMERUN_TAG_DEVICE_ID 0x02
 #define HDHOMERUN_TAG_GETSET_NAME 0x03
 #define HDHOMERUN_TAG_GETSET_VALUE 0x04
+#define HDHOMERUN_TAG_GETSET_LOCKKEY 0x15
 #define HDHOMERUN_TAG_ERROR_MESSAGE 0x05
 
 #define HDHOMERUN_DEVICE_TYPE_WILDCARD 0xFFFFFFFF
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_types.h myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_types.h
--- mythtv/libs/libmythhdhomerun/hdhomerun_types.h	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/hdhomerun_types.h	2009-06-27 10:32:15.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * hdhomerun_types.h
  *
- * Copyright © 2008 Silicondust Engineering Ltd. <www.silicondust.com>.
+ * Copyright Â© 2008 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
  * This library is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public
@@ -15,6 +15,19 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 
 struct hdhomerun_device_t;
@@ -38,14 +51,14 @@ struct hdhomerun_channelscan_program_t {
 	uint16_t virtual_major;
 	uint16_t virtual_minor;
 	uint16_t type;
-	char name[8];
+	char name[32];
 };
 
 #define HDHOMERUN_CHANNELSCAN_MAX_PROGRAM_COUNT 64
 
 struct hdhomerun_channelscan_result_t {
 	char channel_str[64];
-	uint32_t channel_map;
+	uint32_t channelmap;
 	uint32_t frequency;
 	struct hdhomerun_tuner_status_t status;
 	int program_count;
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_video.c myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_video.c
--- mythtv/libs/libmythhdhomerun/hdhomerun_video.c	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/hdhomerun_video.c	2009-06-27 10:37:52.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * hdhomerun_video.c
  *
- * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
+ * Copyright Â© 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
  * This library is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public
@@ -15,11 +15,25 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 
 #include "hdhomerun.h"
 
 struct hdhomerun_video_sock_t {
+	pthread_mutex_t lock;
 	uint8_t *buffer;
 	size_t buffer_size;
 	volatile size_t head;
@@ -28,6 +42,7 @@ struct hdhomerun_video_sock_t {
 	volatile bool_t terminate;
 	pthread_t thread;
 	int sock;
+	uint32_t rtp_sequence;
 	struct hdhomerun_debug_t *dbg;
 	volatile uint32_t packet_count;
 	volatile uint32_t transport_error_count;
@@ -35,7 +50,6 @@ struct hdhomerun_video_sock_t {
 	volatile uint32_t sequence_error_count;
 	volatile uint32_t overflow_error_count;
 	volatile uint8_t sequence[0x2000];
-	uint32_t rtp_sequence;
 };
 
 static THREAD_FUNC_PREFIX hdhomerun_video_thread_execute(void *arg);
@@ -84,6 +98,8 @@ struct hdhomerun_video_sock_t *hdhomerun
 		return NULL;
 	}
 
+	pthread_mutex_init(&vs->lock, NULL);
+
 	/* Reset sequence tracking. */
 	hdhomerun_video_flush(vs);
 
@@ -210,7 +226,7 @@ static void hdhomerun_video_parse_rtp(st
 
 			/* restart pid sequence check */
 			/* can't use memset bcs sequence is volatile */
-			int i;
+                        int i;
 			for (i = 0; i < sizeof(vs->sequence) / sizeof(uint8_t) ; i++)
 				vs->sequence[i] = 0xFF;
 		}
@@ -250,6 +266,8 @@ static THREAD_FUNC_PREFIX hdhomerun_vide
 			return NULL;
 		}
 
+		pthread_mutex_lock(&vs->lock);
+
 		/* Store in ring buffer. */
 		size_t head = vs->head;
 		uint8_t *ptr = vs->buffer + head;
@@ -274,11 +292,14 @@ static THREAD_FUNC_PREFIX hdhomerun_vide
 		/* Check for buffer overflow. */
 		if (head == vs->tail) {
 			vs->overflow_error_count++;
+			pthread_mutex_unlock(&vs->lock);
 			continue;
 		}
 
 		/* Atomic update. */
 		vs->head = head;
+
+		pthread_mutex_unlock(&vs->lock);
 	}
 
 	return NULL;
@@ -286,6 +307,8 @@ static THREAD_FUNC_PREFIX hdhomerun_vide
 
 uint8_t *hdhomerun_video_recv(struct hdhomerun_video_sock_t *vs, size_t max_size, size_t *pactual_size)
 {
+	pthread_mutex_lock(&vs->lock);
+
 	size_t head = vs->head;
 	size_t tail = vs->tail;
 
@@ -302,6 +325,7 @@ uint8_t *hdhomerun_video_recv(struct hdh
 	if (head == tail) {
 		vs->advance = 0;
 		*pactual_size = 0;
+		pthread_mutex_unlock(&vs->lock);
 		return NULL;
 	}
 
@@ -309,6 +333,7 @@ uint8_t *hdhomerun_video_recv(struct hdh
 	if (size == 0) {
 		vs->advance = 0;
 		*pactual_size = 0;
+		pthread_mutex_unlock(&vs->lock);
 		return NULL;
 	}
 
@@ -323,17 +348,21 @@ uint8_t *hdhomerun_video_recv(struct hdh
 	}
 	vs->advance = size;
 	*pactual_size = size;
-	return vs->buffer + tail;
+	uint8_t *result = vs->buffer + tail;
+
+	pthread_mutex_unlock(&vs->lock);
+	return result;
 }
 
 void hdhomerun_video_flush(struct hdhomerun_video_sock_t *vs)
 {
-	/* Atomic update of tail. */
+	pthread_mutex_lock(&vs->lock);
+
 	vs->tail = vs->head;
 	vs->advance = 0;
 
 	/* can't use memset bcs sequence is volatile */
-	int i;
+        int i;
 	for (i = 0; i < sizeof(vs->sequence) / sizeof(uint8_t) ; i++)
 		vs->sequence[i] = 0xFF;
 
@@ -344,19 +373,33 @@ void hdhomerun_video_flush(struct hdhome
 	vs->network_error_count = 0;
 	vs->sequence_error_count = 0;
 	vs->overflow_error_count = 0;
+
+	pthread_mutex_unlock(&vs->lock);
 }
 
 void hdhomerun_video_debug_print_stats(struct hdhomerun_video_sock_t *vs)
 {
-	hdhomerun_debug_printf(vs->dbg, "video sock: pkt=%ld net=%ld te=%ld miss=%ld drop=%ld\n", vs->packet_count, vs->network_error_count, vs->transport_error_count, vs->sequence_error_count, vs->overflow_error_count);
+	struct hdhomerun_video_stats_t stats;
+	hdhomerun_video_get_stats(vs, &stats);
+
+	hdhomerun_debug_printf(vs->dbg, "video sock: pkt=%ld net=%ld te=%ld miss=%ld drop=%ld\n",
+		stats.packet_count, stats.network_error_count,
+		stats.transport_error_count, stats.sequence_error_count,
+		stats.overflow_error_count
+	);
 }
 
 void hdhomerun_video_get_stats(struct hdhomerun_video_sock_t *vs, struct hdhomerun_video_stats_t *stats)
 {
 	memset(stats, 0, sizeof(struct hdhomerun_video_stats_t));
 
+	pthread_mutex_lock(&vs->lock);
+
 	stats->packet_count = vs->packet_count;
 	stats->network_error_count = vs->network_error_count;
 	stats->transport_error_count = vs->transport_error_count;
 	stats->sequence_error_count = vs->sequence_error_count;
+	stats->overflow_error_count = vs->overflow_error_count;
+
+	pthread_mutex_unlock(&vs->lock);
 }
diff -p -r -u -N -X /tmp/diff.exclude.2286 -x myth.20746.0626a -x myth.20746.0626b myth.20746.0626a/mythtv/libs/libmythhdhomerun/hdhomerun_video.h myth.20746.0626b/mythtv/libs/libmythhdhomerun/hdhomerun_video.h
--- mythtv/libs/libmythhdhomerun/hdhomerun_video.h	2009-06-27 10:25:23.000000000 -0500
+++ mythtv/libs/libmythhdhomerun/hdhomerun_video.h	2009-06-27 10:32:15.000000000 -0500
@@ -1,7 +1,7 @@
 /*
  * hdhomerun_video.h
  *
- * Copyright © 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
+ * Copyright Â© 2006 Silicondust Engineering Ltd. <www.silicondust.com>.
  *
  * This library is free software; you can redistribute it and/or 
  * modify it under the terms of the GNU Lesser General Public
@@ -15,6 +15,19 @@
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
+ * 
+ * As a special exception to the GNU Lesser General Public License,
+ * you may link, statically or dynamically, an application with a
+ * publicly distributed version of the Library to produce an
+ * executable file containing portions of the Library, and
+ * distribute that executable file under terms of your choice,
+ * without any of the additional requirements listed in clause 4 of
+ * the GNU Lesser General Public License.
+ * 
+ * By "a publicly distributed version of the Library", we mean
+ * either the unmodified Library as distributed by Silicondust, or a
+ * modified version of the Library that is distributed under the
+ * conditions defined in the GNU Lesser General Public License.
  */
 #ifdef __cplusplus
 extern "C" {
@@ -27,6 +40,7 @@ struct hdhomerun_video_stats_t {
 	uint32_t network_error_count;
 	uint32_t transport_error_count;
 	uint32_t sequence_error_count;
+	uint32_t overflow_error_count;
 };
 
 #define TS_PACKET_SIZE 188
