00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "hdhomerun.h"
00034
00035 struct hdhomerun_channel_entry_t {
00036 struct hdhomerun_channel_entry_t *next;
00037 struct hdhomerun_channel_entry_t *prev;
00038 uint32_t frequency;
00039 uint16_t channel_number;
00040 char name[16];
00041 };
00042
00043 struct hdhomerun_channel_list_t {
00044 struct hdhomerun_channel_entry_t *head;
00045 struct hdhomerun_channel_entry_t *tail;
00046 };
00047
00048 struct hdhomerun_channelmap_range_t {
00049 uint16_t channel_range_start;
00050 uint16_t channel_range_end;
00051 uint32_t frequency;
00052 uint32_t spacing;
00053 };
00054
00055 struct hdhomerun_channelmap_record_t {
00056 const char *channelmap;
00057 const struct hdhomerun_channelmap_range_t *range_list;
00058 const char *channelmap_scan_group;
00059 const char *countrycodes;
00060 };
00061
00062
00063 static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_au_bcast[] = {
00064 { 5, 12, 177500000, 7000000},
00065 { 21, 69, 480500000, 7000000},
00066 { 0, 0, 0, 0}
00067 };
00068
00069
00070 static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_eu_bcast[] = {
00071 { 5, 12, 177500000, 7000000},
00072 { 21, 69, 474000000, 8000000},
00073 { 0, 0, 0, 0}
00074 };
00075
00076
00077 static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_eu_cable[] = {
00078 { 50, 998, 50000000, 1000000},
00079 { 0, 0, 0, 0}
00080 };
00081
00082
00083 static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_us_bcast[] = {
00084 { 2, 4, 57000000, 6000000},
00085 { 5, 6, 79000000, 6000000},
00086 { 7, 13, 177000000, 6000000},
00087 { 14, 69, 473000000, 6000000},
00088 { 0, 0, 0, 0}
00089 };
00090
00091
00092 static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_us_cable[] = {
00093 { 2, 4, 57000000, 6000000},
00094 { 5, 6, 79000000, 6000000},
00095 { 7, 13, 177000000, 6000000},
00096 { 14, 22, 123000000, 6000000},
00097 { 23, 94, 219000000, 6000000},
00098 { 95, 99, 93000000, 6000000},
00099 {100, 158, 651000000, 6000000},
00100 { 0, 0, 0, 0}
00101 };
00102
00103
00104 static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_us_hrc[] = {
00105 { 2, 4, 55752700, 6000300},
00106 { 5, 6, 79753900, 6000300},
00107 { 7, 13, 175758700, 6000300},
00108 { 14, 22, 121756000, 6000300},
00109 { 23, 94, 217760800, 6000300},
00110 { 95, 99, 91754500, 6000300},
00111 {100, 158, 649782400, 6000300},
00112 { 0, 0, 0, 0}
00113 };
00114
00115
00116 static const struct hdhomerun_channelmap_range_t hdhomerun_channelmap_range_us_irc[] = {
00117 { 2, 4, 57012500, 6000000},
00118 { 5, 6, 81012500, 6000000},
00119 { 7, 13, 177012500, 6000000},
00120 { 14, 22, 123012500, 6000000},
00121 { 23, 41, 219012500, 6000000},
00122 { 42, 42, 333025000, 6000000},
00123 { 43, 94, 339012500, 6000000},
00124 { 95, 97, 93012500, 6000000},
00125 { 98, 99, 111025000, 6000000},
00126 {100, 158, 651012500, 6000000},
00127 { 0, 0, 0, 0}
00128 };
00129
00130 static const struct hdhomerun_channelmap_record_t hdhomerun_channelmap_table[] = {
00131 {"au-bcast", hdhomerun_channelmap_range_au_bcast, "au-bcast", "AU"},
00132 {"au-cable", hdhomerun_channelmap_range_eu_cable, "au-cable", "AU"},
00133 {"eu-bcast", hdhomerun_channelmap_range_eu_bcast, "eu-bcast", "EU PA"},
00134 {"eu-cable", hdhomerun_channelmap_range_eu_cable, "eu-cable", "EU"},
00135 {"tw-bcast", hdhomerun_channelmap_range_us_bcast, "tw-bcast", "TW"},
00136 {"tw-cable", hdhomerun_channelmap_range_us_cable, "tw-cable", "TW"},
00137
00138 {"us-bcast", hdhomerun_channelmap_range_us_bcast, "us-bcast", "CA US"},
00139 {"us-cable", hdhomerun_channelmap_range_us_cable, "us-cable us-hrc us-irc", "CA PA US"},
00140 {"us-hrc", hdhomerun_channelmap_range_us_hrc , "us-cable us-hrc us-irc", "CA PA US"},
00141 {"us-irc", hdhomerun_channelmap_range_us_irc, "us-cable us-hrc us-irc", "CA PA US"},
00142
00143 {NULL, NULL, NULL, NULL}
00144 };
00145
00146 const char *hdhomerun_channelmap_get_channelmap_from_country_source(const char *countrycode, const char *source)
00147 {
00148 bool_t country_found = FALSE;
00149
00150 const struct hdhomerun_channelmap_record_t *record = hdhomerun_channelmap_table;
00151 while (record->channelmap) {
00152 if (!strstr(record->countrycodes, countrycode)) {
00153 record++;
00154 continue;
00155 }
00156
00157 if (strstr(record->channelmap, source)) {
00158 return record->channelmap;
00159 }
00160
00161 country_found = TRUE;
00162 record++;
00163 }
00164
00165 if (!country_found) {
00166 return hdhomerun_channelmap_get_channelmap_from_country_source("EU", source);
00167 }
00168
00169 return NULL;
00170 }
00171
00172 const char *hdhomerun_channelmap_get_channelmap_scan_group(const char *channelmap)
00173 {
00174 const struct hdhomerun_channelmap_record_t *record = hdhomerun_channelmap_table;
00175 while (record->channelmap) {
00176 if (strstr(channelmap, record->channelmap)) {
00177 return record->channelmap_scan_group;
00178 }
00179 record++;
00180 }
00181
00182 return NULL;
00183 }
00184
00185 uint16_t hdhomerun_channel_entry_channel_number(struct hdhomerun_channel_entry_t *entry)
00186 {
00187 return entry->channel_number;
00188 }
00189
00190 uint32_t hdhomerun_channel_entry_frequency(struct hdhomerun_channel_entry_t *entry)
00191 {
00192 return entry->frequency;
00193 }
00194
00195 const char *hdhomerun_channel_entry_name(struct hdhomerun_channel_entry_t *entry)
00196 {
00197 return entry->name;
00198 }
00199
00200 struct hdhomerun_channel_entry_t *hdhomerun_channel_list_first(struct hdhomerun_channel_list_t *channel_list)
00201 {
00202 return channel_list->head;
00203 }
00204
00205 struct hdhomerun_channel_entry_t *hdhomerun_channel_list_last(struct hdhomerun_channel_list_t *channel_list)
00206 {
00207 return channel_list->tail;
00208 }
00209
00210 struct hdhomerun_channel_entry_t *hdhomerun_channel_list_next(struct hdhomerun_channel_list_t *channel_list, struct hdhomerun_channel_entry_t *entry)
00211 {
00212 return entry->next;
00213 }
00214
00215 struct hdhomerun_channel_entry_t *hdhomerun_channel_list_prev(struct hdhomerun_channel_list_t *channel_list, struct hdhomerun_channel_entry_t *entry)
00216 {
00217 return entry->prev;
00218 }
00219
00220 uint32_t hdhomerun_channel_list_total_count(struct hdhomerun_channel_list_t *channel_list)
00221 {
00222 uint32_t count = 0;
00223
00224 struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_first(channel_list);
00225 while (entry) {
00226 count++;
00227 entry = hdhomerun_channel_list_next(channel_list, entry);
00228 }
00229
00230 return count;
00231 }
00232
00233 uint32_t hdhomerun_channel_list_frequency_count(struct hdhomerun_channel_list_t *channel_list)
00234 {
00235 uint32_t count = 0;
00236 uint32_t last_frequency = 0;
00237
00238 struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_first(channel_list);
00239 while (entry) {
00240 if (entry->frequency != last_frequency) {
00241 last_frequency = entry->frequency;
00242 count++;
00243 }
00244
00245 entry = hdhomerun_channel_list_next(channel_list, entry);
00246 }
00247
00248 return count;
00249 }
00250
00251 uint32_t hdhomerun_channel_frequency_round(uint32_t frequency, uint32_t resolution)
00252 {
00253 frequency += resolution / 2;
00254 return (frequency / resolution) * resolution;
00255 }
00256
00257 uint32_t hdhomerun_channel_frequency_round_normal(uint32_t frequency)
00258 {
00259 return hdhomerun_channel_frequency_round(frequency, 125000);
00260 }
00261
00262 uint32_t hdhomerun_channel_number_to_frequency(struct hdhomerun_channel_list_t *channel_list, uint16_t channel_number)
00263 {
00264 struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_first(channel_list);
00265 while (entry) {
00266 if (entry->channel_number == channel_number) {
00267 return entry->frequency;
00268 }
00269
00270 entry = hdhomerun_channel_list_next(channel_list, entry);
00271 }
00272
00273 return 0;
00274 }
00275
00276 uint16_t hdhomerun_channel_frequency_to_number(struct hdhomerun_channel_list_t *channel_list, uint32_t frequency)
00277 {
00278 frequency = hdhomerun_channel_frequency_round_normal(frequency);
00279
00280 struct hdhomerun_channel_entry_t *entry = hdhomerun_channel_list_first(channel_list);
00281 while (entry) {
00282 if (entry->frequency == frequency) {
00283 return entry->channel_number;
00284 }
00285 if (entry->frequency > frequency) {
00286 return 0;
00287 }
00288
00289 entry = hdhomerun_channel_list_next(channel_list, entry);
00290 }
00291
00292 return 0;
00293 }
00294
00295 static void hdhomerun_channel_list_build_insert(struct hdhomerun_channel_list_t *channel_list, struct hdhomerun_channel_entry_t *entry)
00296 {
00297 struct hdhomerun_channel_entry_t *prev = NULL;
00298 struct hdhomerun_channel_entry_t *next = channel_list->head;
00299
00300 while (next) {
00301 if (next->frequency > entry->frequency) {
00302 break;
00303 }
00304
00305 prev = next;
00306 next = next->next;
00307 }
00308
00309 entry->prev = prev;
00310 entry->next = next;
00311
00312 if (prev) {
00313 prev->next = entry;
00314 } else {
00315 channel_list->head = entry;
00316 }
00317
00318 if (next) {
00319 next->prev = entry;
00320 } else {
00321 channel_list->tail = entry;
00322 }
00323 }
00324
00325 static void hdhomerun_channel_list_build_range(struct hdhomerun_channel_list_t *channel_list, const char *channelmap, const struct hdhomerun_channelmap_range_t *range)
00326 {
00327 uint16_t channel_number;
00328 for (channel_number = range->channel_range_start; channel_number <= range->channel_range_end; channel_number++) {
00329 struct hdhomerun_channel_entry_t *entry = (struct hdhomerun_channel_entry_t *)calloc(1, sizeof(struct hdhomerun_channel_entry_t));
00330 if (!entry) {
00331 return;
00332 }
00333
00334 entry->channel_number = channel_number;
00335 entry->frequency = range->frequency + ((uint32_t)(channel_number - range->channel_range_start) * range->spacing);
00336 entry->frequency = hdhomerun_channel_frequency_round_normal(entry->frequency);
00337 sprintf(entry->name, "%s:%u", channelmap, entry->channel_number);
00338
00339 hdhomerun_channel_list_build_insert(channel_list, entry);
00340 }
00341 }
00342
00343 static void hdhomerun_channel_list_build_ranges(struct hdhomerun_channel_list_t *channel_list, const struct hdhomerun_channelmap_record_t *record)
00344 {
00345 const struct hdhomerun_channelmap_range_t *range = record->range_list;
00346 while (range->frequency) {
00347 hdhomerun_channel_list_build_range(channel_list, record->channelmap, range);
00348 range++;
00349 }
00350 }
00351
00352 void hdhomerun_channel_list_destroy(struct hdhomerun_channel_list_t *channel_list)
00353 {
00354 while (channel_list->head) {
00355 struct hdhomerun_channel_entry_t *entry = channel_list->head;
00356 channel_list->head = entry->next;
00357 free(entry);
00358 }
00359
00360 free(channel_list);
00361 }
00362
00363 struct hdhomerun_channel_list_t *hdhomerun_channel_list_create(const char *channelmap)
00364 {
00365 struct hdhomerun_channel_list_t *channel_list = (struct hdhomerun_channel_list_t *)calloc(1, sizeof(struct hdhomerun_channel_list_t));
00366 if (!channel_list) {
00367 return NULL;
00368 }
00369
00370 const struct hdhomerun_channelmap_record_t *record = hdhomerun_channelmap_table;
00371 while (record->channelmap) {
00372 if (!strstr(channelmap, record->channelmap)) {
00373 record++;
00374 continue;
00375 }
00376
00377 hdhomerun_channel_list_build_ranges(channel_list, record);
00378 record++;
00379 }
00380
00381 if (!channel_list->head) {
00382 free(channel_list);
00383 return NULL;
00384 }
00385
00386 return channel_list;
00387 }