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_device_t {
00036 struct hdhomerun_control_sock_t *cs;
00037 struct hdhomerun_video_sock_t *vs;
00038 struct hdhomerun_debug_t *dbg;
00039 struct hdhomerun_channelscan_t *scan;
00040 uint32_t device_id;
00041 unsigned int tuner;
00042 uint32_t lockkey;
00043 char name[32];
00044 char model[32];
00045 };
00046
00047 static void hdhomerun_device_set_update(struct hdhomerun_device_t *hd)
00048 {
00049
00050 *hd->model = 0;
00051
00052
00053 sprintf(hd->name, "%08lX-%u", (unsigned long)hd->device_id, hd->tuner);
00054 }
00055
00056 void hdhomerun_device_set_device(struct hdhomerun_device_t *hd, uint32_t device_id, uint32_t device_ip)
00057 {
00058 hdhomerun_control_set_device(hd->cs, device_id, device_ip);
00059
00060 if ((device_id == 0) || (device_id == HDHOMERUN_DEVICE_ID_WILDCARD)) {
00061 device_id = hdhomerun_control_get_device_id(hd->cs);
00062 }
00063
00064 hd->device_id = device_id;
00065 hdhomerun_device_set_update(hd);
00066 }
00067
00068 void hdhomerun_device_set_tuner(struct hdhomerun_device_t *hd, unsigned int tuner)
00069 {
00070 hd->tuner = tuner;
00071 hdhomerun_device_set_update(hd);
00072 }
00073
00074 struct hdhomerun_device_t *hdhomerun_device_create(uint32_t device_id, uint32_t device_ip, unsigned int tuner, struct hdhomerun_debug_t *dbg)
00075 {
00076 struct hdhomerun_device_t *hd = (struct hdhomerun_device_t *)calloc(1, sizeof(struct hdhomerun_device_t));
00077 if (!hd) {
00078 hdhomerun_debug_printf(dbg, "hdhomerun_device_create: failed to allocate device object\n");
00079 return NULL;
00080 }
00081
00082 hd->dbg = dbg;
00083
00084 hd->cs = hdhomerun_control_create(0, 0, hd->dbg);
00085 if (!hd->cs) {
00086 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_create: failed to create control object\n");
00087 free(hd);
00088 return NULL;
00089 }
00090
00091 hdhomerun_device_set_device(hd, device_id, device_ip);
00092 hdhomerun_device_set_tuner(hd, tuner);
00093
00094 return hd;
00095 }
00096
00097 void hdhomerun_device_destroy(struct hdhomerun_device_t *hd)
00098 {
00099 if (hd->scan) {
00100 channelscan_destroy(hd->scan);
00101 }
00102
00103 if (hd->vs) {
00104 hdhomerun_video_destroy(hd->vs);
00105 }
00106
00107 hdhomerun_control_destroy(hd->cs);
00108
00109 free(hd);
00110 }
00111
00112 static bool_t is_hex_char(char c)
00113 {
00114 if ((c >= '0') && (c <= '9')) {
00115 return TRUE;
00116 }
00117 if ((c >= 'A') && (c <= 'F')) {
00118 return TRUE;
00119 }
00120 if ((c >= 'a') && (c <= 'f')) {
00121 return TRUE;
00122 }
00123 return FALSE;
00124 }
00125
00126 static struct hdhomerun_device_t *hdhomerun_device_create_from_str_device_id(const char *device_str, struct hdhomerun_debug_t *dbg)
00127 {
00128 int i;
00129 const char *ptr = device_str;
00130 for (i = 0; i < 8; i++) {
00131 if (!is_hex_char(*ptr++)) {
00132 return NULL;
00133 }
00134 }
00135
00136 if (*ptr == 0) {
00137 unsigned long device_id;
00138 if (sscanf(device_str, "%lx", &device_id) != 1) {
00139 return NULL;
00140 }
00141 return hdhomerun_device_create((uint32_t)device_id, 0, 0, dbg);
00142 }
00143
00144 if (*ptr == '-') {
00145 unsigned long device_id;
00146 unsigned int tuner;
00147 if (sscanf(device_str, "%lx-%u", &device_id, &tuner) != 2) {
00148 return NULL;
00149 }
00150 return hdhomerun_device_create((uint32_t)device_id, 0, tuner, dbg);
00151 }
00152
00153 return NULL;
00154 }
00155
00156 static struct hdhomerun_device_t *hdhomerun_device_create_from_str_ip(const char *device_str, struct hdhomerun_debug_t *dbg)
00157 {
00158 unsigned long a[4];
00159 if (sscanf(device_str, "%lu.%lu.%lu.%lu", &a[0], &a[1], &a[2], &a[3]) != 4) {
00160 return NULL;
00161 }
00162
00163 unsigned long device_ip = (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | (a[3] << 0);
00164 return hdhomerun_device_create(HDHOMERUN_DEVICE_ID_WILDCARD, (uint32_t)device_ip, 0, dbg);
00165 }
00166
00167 static struct hdhomerun_device_t *hdhomerun_device_create_from_str_dns(const char *device_str, struct hdhomerun_debug_t *dbg)
00168 {
00169 #if defined(__CYGWIN__)
00170 return NULL;
00171 #else
00172 struct addrinfo hints;
00173 memset(&hints, 0, sizeof(hints));
00174 hints.ai_family = AF_INET;
00175 hints.ai_socktype = SOCK_STREAM;
00176 hints.ai_protocol = IPPROTO_TCP;
00177
00178 struct addrinfo *sock_info;
00179 if (getaddrinfo(device_str, "65001", &hints, &sock_info) != 0) {
00180 return NULL;
00181 }
00182
00183 struct sockaddr_in *sock_addr = (struct sockaddr_in *)sock_info->ai_addr;
00184 uint32_t device_ip = ntohl(sock_addr->sin_addr.s_addr);
00185 freeaddrinfo(sock_info);
00186
00187 if (device_ip == 0) {
00188 return NULL;
00189 }
00190
00191 return hdhomerun_device_create(HDHOMERUN_DEVICE_ID_WILDCARD, (uint32_t)device_ip, 0, dbg);
00192 #endif
00193 }
00194
00195 struct hdhomerun_device_t *hdhomerun_device_create_from_str(const char *device_str, struct hdhomerun_debug_t *dbg)
00196 {
00197 struct hdhomerun_device_t *device = hdhomerun_device_create_from_str_device_id(device_str, dbg);
00198 if (device) {
00199 return device;
00200 }
00201
00202 device = hdhomerun_device_create_from_str_ip(device_str, dbg);
00203 if (device) {
00204 return device;
00205 }
00206
00207 device = hdhomerun_device_create_from_str_dns(device_str, dbg);
00208 if (device) {
00209 return device;
00210 }
00211
00212 return NULL;
00213 }
00214
00215 int hdhomerun_device_set_tuner_from_str(struct hdhomerun_device_t *hd, const char *tuner_str)
00216 {
00217 unsigned int tuner;
00218 if (sscanf(tuner_str, "%u", &tuner) == 1) {
00219 hdhomerun_device_set_tuner(hd, tuner);
00220 return 1;
00221 }
00222 if (sscanf(tuner_str, "/tuner%u", &tuner) == 1) {
00223 hdhomerun_device_set_tuner(hd, tuner);
00224 return 1;
00225 }
00226
00227 return -1;
00228 }
00229
00230 const char *hdhomerun_device_get_name(struct hdhomerun_device_t *hd)
00231 {
00232 return hd->name;
00233 }
00234
00235 uint32_t hdhomerun_device_get_device_id(struct hdhomerun_device_t *hd)
00236 {
00237 return hdhomerun_control_get_device_id(hd->cs);
00238 }
00239
00240 uint32_t hdhomerun_device_get_device_ip(struct hdhomerun_device_t *hd)
00241 {
00242 return hdhomerun_control_get_device_ip(hd->cs);
00243 }
00244
00245 uint32_t hdhomerun_device_get_device_id_requested(struct hdhomerun_device_t *hd)
00246 {
00247 return hdhomerun_control_get_device_id_requested(hd->cs);
00248 }
00249
00250 uint32_t hdhomerun_device_get_device_ip_requested(struct hdhomerun_device_t *hd)
00251 {
00252 return hdhomerun_control_get_device_ip_requested(hd->cs);
00253 }
00254
00255 unsigned int hdhomerun_device_get_tuner(struct hdhomerun_device_t *hd)
00256 {
00257 return hd->tuner;
00258 }
00259
00260 struct hdhomerun_control_sock_t *hdhomerun_device_get_control_sock(struct hdhomerun_device_t *hd)
00261 {
00262 return hd->cs;
00263 }
00264
00265 struct hdhomerun_video_sock_t *hdhomerun_device_get_video_sock(struct hdhomerun_device_t *hd)
00266 {
00267 if (hd->vs) {
00268 return hd->vs;
00269 }
00270
00271 hd->vs = hdhomerun_video_create(0, VIDEO_DATA_BUFFER_SIZE_1S * 2, hd->dbg);
00272 if (!hd->vs) {
00273 hdhomerun_debug_printf(hd->dbg, "hdhomerun_device_get_video_sock: failed to create video object\n");
00274 return NULL;
00275 }
00276
00277 return hd->vs;
00278 }
00279
00280 uint32_t hdhomerun_device_get_local_machine_addr(struct hdhomerun_device_t *hd)
00281 {
00282 return hdhomerun_control_get_local_addr(hd->cs);
00283 }
00284
00285 static uint32_t hdhomerun_device_get_status_parse(const char *status_str, const char *tag)
00286 {
00287 const char *ptr = strstr(status_str, tag);
00288 if (!ptr) {
00289 return 0;
00290 }
00291
00292 unsigned long value = 0;
00293 sscanf(ptr + strlen(tag), "%lu", &value);
00294
00295 return (uint32_t)value;
00296 }
00297
00298 static bool_t hdhomerun_device_get_tuner_status_lock_is_bcast(struct hdhomerun_tuner_status_t *status)
00299 {
00300 if (strcmp(status->lock_str, "8vsb") == 0) {
00301 return TRUE;
00302 }
00303 if (strncmp(status->lock_str, "t8", 2) == 0) {
00304 return TRUE;
00305 }
00306 if (strncmp(status->lock_str, "t7", 2) == 0) {
00307 return TRUE;
00308 }
00309 if (strncmp(status->lock_str, "t6", 2) == 0) {
00310 return TRUE;
00311 }
00312
00313 return FALSE;
00314 }
00315
00316 uint32_t hdhomerun_device_get_tuner_status_ss_color(struct hdhomerun_tuner_status_t *status)
00317 {
00318 unsigned int ss_yellow_min;
00319 unsigned int ss_green_min;
00320
00321 if (!status->lock_supported) {
00322 return HDHOMERUN_STATUS_COLOR_NEUTRAL;
00323 }
00324
00325 if (hdhomerun_device_get_tuner_status_lock_is_bcast(status)) {
00326 ss_yellow_min = 50;
00327 ss_green_min = 75;
00328 } else {
00329 ss_yellow_min = 80;
00330 ss_green_min = 90;
00331 }
00332
00333 if (status->signal_strength >= ss_green_min) {
00334 return HDHOMERUN_STATUS_COLOR_GREEN;
00335 }
00336 if (status->signal_strength >= ss_yellow_min) {
00337 return HDHOMERUN_STATUS_COLOR_YELLOW;
00338 }
00339
00340 return HDHOMERUN_STATUS_COLOR_RED;
00341 }
00342
00343 uint32_t hdhomerun_device_get_tuner_status_snq_color(struct hdhomerun_tuner_status_t *status)
00344 {
00345 if (status->signal_to_noise_quality >= 70) {
00346 return HDHOMERUN_STATUS_COLOR_GREEN;
00347 }
00348 if (status->signal_to_noise_quality >= 50) {
00349 return HDHOMERUN_STATUS_COLOR_YELLOW;
00350 }
00351
00352 return HDHOMERUN_STATUS_COLOR_RED;
00353 }
00354
00355 uint32_t hdhomerun_device_get_tuner_status_seq_color(struct hdhomerun_tuner_status_t *status)
00356 {
00357 if (status->symbol_error_quality >= 100) {
00358 return HDHOMERUN_STATUS_COLOR_GREEN;
00359 }
00360
00361 return HDHOMERUN_STATUS_COLOR_RED;
00362 }
00363
00364 int hdhomerun_device_get_tuner_status(struct hdhomerun_device_t *hd, char **pstatus_str, struct hdhomerun_tuner_status_t *status)
00365 {
00366 memset(status, 0, sizeof(struct hdhomerun_tuner_status_t));
00367
00368 char name[32];
00369 sprintf(name, "/tuner%u/status", hd->tuner);
00370
00371 char *status_str;
00372 int ret = hdhomerun_control_get(hd->cs, name, &status_str, NULL);
00373 if (ret <= 0) {
00374 return ret;
00375 }
00376
00377 if (pstatus_str) {
00378 *pstatus_str = status_str;
00379 }
00380
00381 char *channel = strstr(status_str, "ch=");
00382 if (channel) {
00383 sscanf(channel + 3, "%31s", status->channel);
00384 }
00385
00386 char *lock = strstr(status_str, "lock=");
00387 if (lock) {
00388 sscanf(lock + 5, "%31s", status->lock_str);
00389 }
00390
00391 status->signal_strength = (unsigned int)hdhomerun_device_get_status_parse(status_str, "ss=");
00392 status->signal_to_noise_quality = (unsigned int)hdhomerun_device_get_status_parse(status_str, "snq=");
00393 status->symbol_error_quality = (unsigned int)hdhomerun_device_get_status_parse(status_str, "seq=");
00394 status->raw_bits_per_second = hdhomerun_device_get_status_parse(status_str, "bps=");
00395 status->packets_per_second = hdhomerun_device_get_status_parse(status_str, "pps=");
00396
00397 status->signal_present = status->signal_strength >= 45;
00398
00399 if (strcmp(status->lock_str, "none") != 0) {
00400 if (status->lock_str[0] == '(') {
00401 status->lock_unsupported = TRUE;
00402 } else {
00403 status->lock_supported = TRUE;
00404 }
00405 }
00406
00407 return 1;
00408 }
00409
00410 int hdhomerun_device_get_tuner_streaminfo(struct hdhomerun_device_t *hd, char **pstreaminfo)
00411 {
00412 char name[32];
00413 sprintf(name, "/tuner%u/streaminfo", hd->tuner);
00414 return hdhomerun_control_get(hd->cs, name, pstreaminfo, NULL);
00415 }
00416
00417 int hdhomerun_device_get_tuner_channel(struct hdhomerun_device_t *hd, char **pchannel)
00418 {
00419 char name[32];
00420 sprintf(name, "/tuner%u/channel", hd->tuner);
00421 return hdhomerun_control_get(hd->cs, name, pchannel, NULL);
00422 }
00423
00424 int hdhomerun_device_get_tuner_channelmap(struct hdhomerun_device_t *hd, char **pchannelmap)
00425 {
00426 char name[32];
00427 sprintf(name, "/tuner%u/channelmap", hd->tuner);
00428 return hdhomerun_control_get(hd->cs, name, pchannelmap, NULL);
00429 }
00430
00431 int hdhomerun_device_get_tuner_filter(struct hdhomerun_device_t *hd, char **pfilter)
00432 {
00433 char name[32];
00434 sprintf(name, "/tuner%u/filter", hd->tuner);
00435 return hdhomerun_control_get(hd->cs, name, pfilter, NULL);
00436 }
00437
00438 int hdhomerun_device_get_tuner_program(struct hdhomerun_device_t *hd, char **pprogram)
00439 {
00440 char name[32];
00441 sprintf(name, "/tuner%u/program", hd->tuner);
00442 return hdhomerun_control_get(hd->cs, name, pprogram, NULL);
00443 }
00444
00445 int hdhomerun_device_get_tuner_target(struct hdhomerun_device_t *hd, char **ptarget)
00446 {
00447 char name[32];
00448 sprintf(name, "/tuner%u/target", hd->tuner);
00449 return hdhomerun_control_get(hd->cs, name, ptarget, NULL);
00450 }
00451
00452 int hdhomerun_device_get_tuner_plotsample(struct hdhomerun_device_t *hd, struct hdhomerun_plotsample_t **psamples, size_t *pcount)
00453 {
00454 char name[32];
00455 sprintf(name, "/tuner%u/plotsample", hd->tuner);
00456
00457 char *result;
00458 int ret = hdhomerun_control_get(hd->cs, name, &result, NULL);
00459 if (ret <= 0) {
00460 return ret;
00461 }
00462
00463 struct hdhomerun_plotsample_t *samples = (struct hdhomerun_plotsample_t *)result;
00464 *psamples = samples;
00465 size_t count = 0;
00466
00467 while (1) {
00468 char *ptr = strchr(result, ' ');
00469 if (!ptr) {
00470 break;
00471 }
00472 *ptr++ = 0;
00473
00474 unsigned long raw;
00475 if (sscanf(result, "%lx", &raw) != 1) {
00476 break;
00477 }
00478
00479 uint16_t real = (raw >> 12) & 0x0FFF;
00480 if (real & 0x0800) {
00481 real |= 0xF000;
00482 }
00483
00484 uint16_t imag = (raw >> 0) & 0x0FFF;
00485 if (imag & 0x0800) {
00486 imag |= 0xF000;
00487 }
00488
00489 samples->real = (int16_t)real;
00490 samples->imag = (int16_t)imag;
00491 samples++;
00492 count++;
00493
00494 result = ptr;
00495 }
00496
00497 *pcount = count;
00498 return 1;
00499 }
00500
00501 int hdhomerun_device_get_tuner_lockkey_owner(struct hdhomerun_device_t *hd, char **powner)
00502 {
00503 char name[32];
00504 sprintf(name, "/tuner%u/lockkey", hd->tuner);
00505 return hdhomerun_control_get(hd->cs, name, powner, NULL);
00506 }
00507
00508 int hdhomerun_device_get_ir_target(struct hdhomerun_device_t *hd, char **ptarget)
00509 {
00510 return hdhomerun_control_get(hd->cs, "/ir/target", ptarget, NULL);
00511 }
00512
00513 int hdhomerun_device_get_lineup_location(struct hdhomerun_device_t *hd, char **plocation)
00514 {
00515 return hdhomerun_control_get(hd->cs, "/lineup/location", plocation, NULL);
00516 }
00517
00518 int hdhomerun_device_get_version(struct hdhomerun_device_t *hd, char **pversion_str, uint32_t *pversion_num)
00519 {
00520 char *version_str;
00521 int ret = hdhomerun_control_get(hd->cs, "/sys/version", &version_str, NULL);
00522 if (ret <= 0) {
00523 return ret;
00524 }
00525
00526 if (pversion_str) {
00527 *pversion_str = version_str;
00528 }
00529
00530 if (pversion_num) {
00531 unsigned long version_num;
00532 if (sscanf(version_str, "%lu", &version_num) != 1) {
00533 *pversion_num = 0;
00534 } else {
00535 *pversion_num = (uint32_t)version_num;
00536 }
00537 }
00538
00539 return 1;
00540 }
00541
00542 int hdhomerun_device_set_tuner_channel(struct hdhomerun_device_t *hd, const char *channel)
00543 {
00544 char name[32];
00545 sprintf(name, "/tuner%u/channel", hd->tuner);
00546 return hdhomerun_control_set_with_lockkey(hd->cs, name, channel, hd->lockkey, NULL, NULL);
00547 }
00548
00549 int hdhomerun_device_set_tuner_channelmap(struct hdhomerun_device_t *hd, const char *channelmap)
00550 {
00551 char name[32];
00552 sprintf(name, "/tuner%u/channelmap", hd->tuner);
00553 return hdhomerun_control_set_with_lockkey(hd->cs, name, channelmap, hd->lockkey, NULL, NULL);
00554 }
00555
00556 int hdhomerun_device_set_tuner_filter(struct hdhomerun_device_t *hd, const char *filter)
00557 {
00558 char name[32];
00559 sprintf(name, "/tuner%u/filter", hd->tuner);
00560 return hdhomerun_control_set_with_lockkey(hd->cs, name, filter, hd->lockkey, NULL, NULL);
00561 }
00562
00563 static int hdhomerun_device_set_tuner_filter_by_array_append(char **pptr, char *end, uint16_t range_begin, uint16_t range_end)
00564 {
00565 char *ptr = *pptr;
00566
00567 size_t available = end - ptr;
00568 size_t required;
00569
00570 if (range_begin == range_end) {
00571 required = snprintf(ptr, available, "0x%04x ", range_begin) + 1;
00572 } else {
00573 required = snprintf(ptr, available, "0x%04x-0x%04x ", range_begin, range_end) + 1;
00574 }
00575
00576 if (required > available) {
00577 return FALSE;
00578 }
00579
00580 *pptr = strchr(ptr, 0);
00581 return TRUE;
00582 }
00583
00584 int hdhomerun_device_set_tuner_filter_by_array(struct hdhomerun_device_t *hd, unsigned char filter_array[0x2000])
00585 {
00586 char filter[1024];
00587 char *ptr = filter;
00588 char *end = filter + sizeof(filter);
00589
00590 uint16_t range_begin = 0xFFFF;
00591 uint16_t range_end = 0xFFFF;
00592
00593 uint16_t i;
00594 for (i = 0; i <= 0x1FFF; i++) {
00595 if (!filter_array[i]) {
00596 if (range_begin == 0xFFFF) {
00597 continue;
00598 }
00599 if (!hdhomerun_device_set_tuner_filter_by_array_append(&ptr, end, range_begin, range_end)) {
00600 return 0;
00601 }
00602 range_begin = 0xFFFF;
00603 range_end = 0xFFFF;
00604 continue;
00605 }
00606
00607 if (range_begin == 0xFFFF) {
00608 range_begin = i;
00609 range_end = i;
00610 continue;
00611 }
00612
00613 range_end = i;
00614 }
00615
00616 if (range_begin != 0xFFFF) {
00617 if (!hdhomerun_device_set_tuner_filter_by_array_append(&ptr, end, range_begin, range_end)) {
00618 return 0;
00619 }
00620 }
00621
00622
00623 if (ptr > filter) {
00624 ptr--;
00625 }
00626 *ptr = 0;
00627
00628 return hdhomerun_device_set_tuner_filter(hd, filter);
00629 }
00630
00631 int hdhomerun_device_set_tuner_program(struct hdhomerun_device_t *hd, const char *program)
00632 {
00633 char name[32];
00634 sprintf(name, "/tuner%u/program", hd->tuner);
00635 return hdhomerun_control_set_with_lockkey(hd->cs, name, program, hd->lockkey, NULL, NULL);
00636 }
00637
00638 int hdhomerun_device_set_tuner_target(struct hdhomerun_device_t *hd, const char *target)
00639 {
00640 char name[32];
00641 sprintf(name, "/tuner%u/target", hd->tuner);
00642 return hdhomerun_control_set_with_lockkey(hd->cs, name, target, hd->lockkey, NULL, NULL);
00643 }
00644
00645 int hdhomerun_device_set_tuner_target_to_local_protocol(struct hdhomerun_device_t *hd, const char *protocol)
00646 {
00647
00648 hdhomerun_device_get_video_sock(hd);
00649 if (!hd->vs) {
00650 return -1;
00651 }
00652
00653
00654 char target[64];
00655 uint32_t local_ip = hdhomerun_control_get_local_addr(hd->cs);
00656 uint16_t local_port = hdhomerun_video_get_local_port(hd->vs);
00657 sprintf(target, "%s://%u.%u.%u.%u:%u",
00658 protocol,
00659 (unsigned int)(local_ip >> 24) & 0xFF, (unsigned int)(local_ip >> 16) & 0xFF,
00660 (unsigned int)(local_ip >> 8) & 0xFF, (unsigned int)(local_ip >> 0) & 0xFF,
00661 (unsigned int)local_port
00662 );
00663
00664 return hdhomerun_device_set_tuner_target(hd, target);
00665 }
00666
00667 int hdhomerun_device_set_tuner_target_to_local(struct hdhomerun_device_t *hd)
00668 {
00669 return hdhomerun_device_set_tuner_target_to_local_protocol(hd, HDHOMERUN_TARGET_PROTOCOL_UDP);
00670 }
00671
00672 int hdhomerun_device_set_ir_target(struct hdhomerun_device_t *hd, const char *target)
00673 {
00674 return hdhomerun_control_set(hd->cs, "/ir/target", target, NULL, NULL);
00675 }
00676
00677 int hdhomerun_device_set_lineup_location(struct hdhomerun_device_t *hd, const char *location)
00678 {
00679 return hdhomerun_control_set(hd->cs, "/lineup/location", location, NULL, NULL);
00680 }
00681
00682 int hdhomerun_device_get_var(struct hdhomerun_device_t *hd, const char *name, char **pvalue, char **perror)
00683 {
00684 return hdhomerun_control_get(hd->cs, name, pvalue, perror);
00685 }
00686
00687 int hdhomerun_device_set_var(struct hdhomerun_device_t *hd, const char *name, const char *value, char **pvalue, char **perror)
00688 {
00689 return hdhomerun_control_set_with_lockkey(hd->cs, name, value, hd->lockkey, pvalue, perror);
00690 }
00691
00692 int hdhomerun_device_tuner_lockkey_request(struct hdhomerun_device_t *hd, char **perror)
00693 {
00694 uint32_t new_lockkey = (uint32_t)getcurrenttime();
00695
00696 char name[32];
00697 sprintf(name, "/tuner%u/lockkey", hd->tuner);
00698
00699 char new_lockkey_str[64];
00700 sprintf(new_lockkey_str, "%u", (unsigned int)new_lockkey);
00701
00702 int ret = hdhomerun_control_set_with_lockkey(hd->cs, name, new_lockkey_str, hd->lockkey, NULL, perror);
00703 if (ret <= 0) {
00704 hd->lockkey = 0;
00705 return ret;
00706 }
00707
00708 hd->lockkey = new_lockkey;
00709 return ret;
00710 }
00711
00712 int hdhomerun_device_tuner_lockkey_release(struct hdhomerun_device_t *hd)
00713 {
00714 if (hd->lockkey == 0) {
00715 return 1;
00716 }
00717
00718 char name[32];
00719 sprintf(name, "/tuner%u/lockkey", hd->tuner);
00720 int ret = hdhomerun_control_set_with_lockkey(hd->cs, name, "none", hd->lockkey, NULL, NULL);
00721
00722 hd->lockkey = 0;
00723 return ret;
00724 }
00725
00726 int hdhomerun_device_tuner_lockkey_force(struct hdhomerun_device_t *hd)
00727 {
00728 char name[32];
00729 sprintf(name, "/tuner%u/lockkey", hd->tuner);
00730 int ret = hdhomerun_control_set(hd->cs, name, "force", NULL, NULL);
00731
00732 hd->lockkey = 0;
00733 return ret;
00734 }
00735
00736 void hdhomerun_device_tuner_lockkey_use_value(struct hdhomerun_device_t *hd, uint32_t lockkey)
00737 {
00738 hd->lockkey = lockkey;
00739 }
00740
00741 int hdhomerun_device_wait_for_lock(struct hdhomerun_device_t *hd, struct hdhomerun_tuner_status_t *status)
00742 {
00743
00744 msleep(250);
00745
00746
00747 uint64_t timeout = getcurrenttime() + 2500;
00748 while (1) {
00749
00750 int ret = hdhomerun_device_get_tuner_status(hd, NULL, status);
00751 if (ret <= 0) {
00752 return ret;
00753 }
00754
00755 if (!status->signal_present) {
00756 return 1;
00757 }
00758 if (status->lock_supported || status->lock_unsupported) {
00759 return 1;
00760 }
00761
00762 if (getcurrenttime() >= timeout) {
00763 return 1;
00764 }
00765
00766 msleep(250);
00767 }
00768 }
00769
00770 int hdhomerun_device_stream_start(struct hdhomerun_device_t *hd)
00771 {
00772
00773 int ret = hdhomerun_device_stream_refresh_target(hd);
00774 if (ret <= 0) {
00775 return ret;
00776 }
00777
00778
00779 msleep(64);
00780 hdhomerun_video_flush(hd->vs);
00781
00782
00783 return 1;
00784 }
00785
00786 int hdhomerun_device_stream_refresh_target(struct hdhomerun_device_t *hd)
00787 {
00788 int ret = hdhomerun_device_set_tuner_target_to_local_protocol(hd, HDHOMERUN_TARGET_PROTOCOL_RTP);
00789 if (ret == 0) {
00790 ret = hdhomerun_device_set_tuner_target_to_local_protocol(hd, HDHOMERUN_TARGET_PROTOCOL_UDP);
00791 }
00792 return ret;
00793 }
00794
00795 uint8_t *hdhomerun_device_stream_recv(struct hdhomerun_device_t *hd, size_t max_size, size_t *pactual_size)
00796 {
00797 if (!hd->vs) {
00798 return NULL;
00799 }
00800 return hdhomerun_video_recv(hd->vs, max_size, pactual_size);
00801 }
00802
00803 void hdhomerun_device_stream_flush(struct hdhomerun_device_t *hd)
00804 {
00805 hdhomerun_video_flush(hd->vs);
00806 }
00807
00808 void hdhomerun_device_stream_stop(struct hdhomerun_device_t *hd)
00809 {
00810 hdhomerun_device_set_tuner_target(hd, "none");
00811 }
00812
00813 int hdhomerun_device_channelscan_init(struct hdhomerun_device_t *hd, const char *channelmap)
00814 {
00815 if (hd->scan) {
00816 channelscan_destroy(hd->scan);
00817 }
00818
00819 hd->scan = channelscan_create(hd, channelmap);
00820 if (!hd->scan) {
00821 return -1;
00822 }
00823
00824 return 1;
00825 }
00826
00827 int hdhomerun_device_channelscan_advance(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result)
00828 {
00829 if (!hd->scan) {
00830 return 0;
00831 }
00832
00833 int ret = channelscan_advance(hd->scan, result);
00834 if (ret <= 0) {
00835 channelscan_destroy(hd->scan);
00836 hd->scan = NULL;
00837 }
00838
00839 return ret;
00840 }
00841
00842 int hdhomerun_device_channelscan_detect(struct hdhomerun_device_t *hd, struct hdhomerun_channelscan_result_t *result)
00843 {
00844 if (!hd->scan) {
00845 return 0;
00846 }
00847
00848 int ret = channelscan_detect(hd->scan, result);
00849 if (ret <= 0) {
00850 channelscan_destroy(hd->scan);
00851 hd->scan = NULL;
00852 }
00853
00854 return ret;
00855 }
00856
00857 uint8_t hdhomerun_device_channelscan_get_progress(struct hdhomerun_device_t *hd)
00858 {
00859 if (!hd->scan) {
00860 return 0;
00861 }
00862
00863 return channelscan_get_progress(hd->scan);
00864 }
00865
00866 int hdhomerun_device_firmware_version_check(struct hdhomerun_device_t *hd, uint32_t features)
00867 {
00868 uint32_t version;
00869 if (hdhomerun_device_get_version(hd, NULL, &version) <= 0) {
00870 return -1;
00871 }
00872
00873 if (version < 20070219) {
00874 return 0;
00875 }
00876
00877 return 1;
00878 }
00879
00880 const char *hdhomerun_device_get_model_str(struct hdhomerun_device_t *hd)
00881 {
00882 if (*hd->model) {
00883 return hd->model;
00884 }
00885
00886 char *model_str;
00887 int ret = hdhomerun_control_get(hd->cs, "/sys/model", &model_str, NULL);
00888 if (ret < 0) {
00889 return NULL;
00890 }
00891 if (ret == 0) {
00892 model_str = "hdhomerun_atsc";
00893 }
00894
00895 strncpy(hd->model, model_str, sizeof(hd->model) - 1);
00896 hd->model[sizeof(hd->model) - 1] = 0;
00897
00898 return hd->model;
00899 }
00900
00901 int hdhomerun_device_upgrade(struct hdhomerun_device_t *hd, FILE *upgrade_file)
00902 {
00903 hdhomerun_control_set(hd->cs, "/tuner0/lockkey", "force", NULL, NULL);
00904 hdhomerun_control_set(hd->cs, "/tuner0/channel", "none", NULL, NULL);
00905
00906 hdhomerun_control_set(hd->cs, "/tuner1/lockkey", "force", NULL, NULL);
00907 hdhomerun_control_set(hd->cs, "/tuner1/channel", "none", NULL, NULL);
00908
00909 return hdhomerun_control_upgrade(hd->cs, upgrade_file);
00910 }
00911
00912 void hdhomerun_device_debug_print_video_stats(struct hdhomerun_device_t *hd)
00913 {
00914 if (!hdhomerun_debug_enabled(hd->dbg)) {
00915 return;
00916 }
00917
00918 char name[32];
00919 sprintf(name, "/tuner%u/debug", hd->tuner);
00920
00921 char *debug_str;
00922 char *error_str;
00923 int ret = hdhomerun_control_get(hd->cs, name, &debug_str, &error_str);
00924 if (ret < 0) {
00925 hdhomerun_debug_printf(hd->dbg, "video dev: communication error getting debug stats\n");
00926 return;
00927 }
00928
00929 if (error_str) {
00930 hdhomerun_debug_printf(hd->dbg, "video dev: %s\n", error_str);
00931 } else {
00932 hdhomerun_debug_printf(hd->dbg, "video dev: %s\n", debug_str);
00933 }
00934
00935 if (hd->vs) {
00936 hdhomerun_video_debug_print_stats(hd->vs);
00937 }
00938 }
00939
00940 void hdhomerun_device_get_video_stats(struct hdhomerun_device_t *hd, struct hdhomerun_video_stats_t *stats)
00941 {
00942 hdhomerun_video_get_stats(hd->vs, stats);
00943 }