int channelscan_advance(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result) { memset(result, 0, sizeof(struct hdhomerun_channelscan_result_t)); struct hdhomerun_channel_entry_t *entry = scan->next_channel; if (!entry) { return 0; } /* Combine channels with same frequency. */ result->frequency = hdhomerun_channel_entry_frequency(entry); char *ptr = result->channel_str; char *end = result->channel_str + sizeof(result->channel_str); hdhomerun_sprintf(ptr, end, hdhomerun_channel_entry_name(entry)); while (1) { entry = hdhomerun_channel_list_prev(scan->channel_list, entry); if (!entry) { scan->next_channel = NULL; break; } if (hdhomerun_channel_entry_frequency(entry) != result->frequency) { scan->next_channel = entry; break; } ptr = strchr(ptr, 0); hdhomerun_sprintf(ptr, end, ", %s", hdhomerun_channel_entry_name(entry)); } return 1; }
int hdhomerun_device_selector_load_from_windows_registry(struct hdhomerun_device_selector_t *hds, wchar_t *wsource) { HKEY tuners_key; LONG ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Silicondust\\HDHomeRun\\Tuners", 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS, &tuners_key); if (ret != ERROR_SUCCESS) { hdhomerun_debug_printf(hds->dbg, "hdhomerun_device_selector_load_from_windows_registry: failed to open tuners registry key (%ld)\n", (long)ret); return 0; } int count = 0; DWORD index = 0; while (1) { /* Next tuner device. */ wchar_t wdevice_str[32]; DWORD size = sizeof(wdevice_str); ret = RegEnumKeyEx(tuners_key, index++, wdevice_str, &size, NULL, NULL, NULL, NULL); if (ret != ERROR_SUCCESS) { break; } /* Check device configuation. */ HKEY device_key; ret = RegOpenKeyEx(tuners_key, wdevice_str, 0, KEY_QUERY_VALUE, &device_key); if (ret != ERROR_SUCCESS) { hdhomerun_debug_printf(hds->dbg, "hdhomerun_device_selector_load_from_windows_registry: failed to open registry key for %S (%ld)\n", wdevice_str, (long)ret); continue; } wchar_t wsource_test[32]; size = sizeof(wsource_test); if (RegQueryValueEx(device_key, L"Source", NULL, NULL, (LPBYTE)&wsource_test, &size) != ERROR_SUCCESS) { wsprintf(wsource_test, L"Unknown"); } RegCloseKey(device_key); if (_wcsicmp(wsource_test, wsource) != 0) { continue; } /* Create and add device. */ char device_str[32]; hdhomerun_sprintf(device_str, device_str + sizeof(device_str), "%S", wdevice_str); count += hdhomerun_device_selector_load_from_str(hds, device_str); } RegCloseKey(tuners_key); return count; }
static void hdhomerun_channel_list_build_range(struct hdhomerun_channel_list_t *channel_list, const char *channelmap, const struct hdhomerun_channelmap_range_t *range) { uint16_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_number = channel_number; entry->frequency = range->frequency + ((uint32_t)(channel_number - range->channel_range_start) * range->spacing); entry->frequency = hdhomerun_channel_frequency_round_normal(entry->frequency); hdhomerun_sprintf(entry->name, entry->name + sizeof(entry->name), "%s:%u", channelmap, entry->channel_number); hdhomerun_channel_list_build_insert(channel_list, entry); } }
static int channelscan_find_lock(struct hdhomerun_channelscan_t *scan, uint32_t frequency, struct hdhomerun_channelscan_result_t *result) { /* Set channel. */ char channel_str[64]; hdhomerun_sprintf(channel_str, channel_str + sizeof(channel_str), "auto:%u", (unsigned int)frequency); int ret = hdhomerun_device_set_tuner_channel(scan->hd, channel_str); if (ret <= 0) { return ret; } /* Wait for lock. */ ret = hdhomerun_device_wait_for_lock(scan->hd, &result->status); if (ret <= 0) { return ret; } if (!result->status.lock_supported) { return 1; } /* Wait for symbol quality = 100%. */ uint64_t timeout = getcurrenttime() + 5000; while (1) { ret = hdhomerun_device_get_tuner_status(scan->hd, NULL, &result->status); if (ret <= 0) { return ret; } if (result->status.symbol_error_quality == 100) { return 1; } if (getcurrenttime() >= timeout) { return 1; } msleep_approx(250); } }
static int channelscan_detect_programs(struct hdhomerun_channelscan_t *scan, struct hdhomerun_channelscan_result_t *result, bool_t *pchanged, bool_t *pincomplete) { *pchanged = FALSE; *pincomplete = FALSE; char *streaminfo; int ret = hdhomerun_device_get_tuner_streaminfo(scan->hd, &streaminfo); if (ret <= 0) { return ret; } char *next_line = streaminfo; int program_count = 0; while (1) { char *line = next_line; next_line = strchr(line, '\n'); if (!next_line) { break; } *next_line++ = 0; unsigned int transport_stream_id; if (sscanf(line, "tsid=0x%x", &transport_stream_id) == 1) { result->transport_stream_id = transport_stream_id; result->transport_stream_id_detected = TRUE; continue; } unsigned int original_network_id; if (sscanf(line, "onid=0x%x", &original_network_id) == 1) { result->original_network_id = original_network_id; result->original_network_id_detected = TRUE; continue; } if (program_count >= HDHOMERUN_CHANNELSCAN_MAX_PROGRAM_COUNT) { continue; } struct hdhomerun_channelscan_program_t program; memset(&program, 0, sizeof(program)); hdhomerun_sprintf(program.program_str, program.program_str + sizeof(program.program_str), "%s", line); unsigned int program_number; unsigned int virtual_major, virtual_minor; if (sscanf(line, "%u: %u.%u", &program_number, &virtual_major, &virtual_minor) != 3) { if (sscanf(line, "%u: %u", &program_number, &virtual_major) != 2) { continue; } virtual_minor = 0; } program.program_number = program_number; program.virtual_major = virtual_major; program.virtual_minor = virtual_minor; channelscan_extract_name(&program, line); if (strstr(line, "(control)")) { program.type = HDHOMERUN_CHANNELSCAN_PROGRAM_CONTROL; } else if (strstr(line, "(encrypted)")) { program.type = HDHOMERUN_CHANNELSCAN_PROGRAM_ENCRYPTED; } else if (strstr(line, "(no data)")) { program.type = HDHOMERUN_CHANNELSCAN_PROGRAM_NODATA; *pincomplete = TRUE; } else { program.type = HDHOMERUN_CHANNELSCAN_PROGRAM_NORMAL; if ((program.virtual_major == 0) || (program.name[0] == 0)) { *pincomplete = TRUE; } } if (memcmp(&result->programs[program_count], &program, sizeof(program)) != 0) { memcpy(&result->programs[program_count], &program, sizeof(program)); *pchanged = TRUE; } program_count++; } if (program_count == 0) { *pincomplete = TRUE; } if (result->program_count != program_count) { result->program_count = program_count; *pchanged = TRUE; } return 1; }
void hdhomerun_debug_vprintf(struct hdhomerun_debug_t *dbg, const char *fmt, va_list args) { if (!dbg) { return; } if (!dbg->enabled) { return; } struct hdhomerun_debug_message_t *message = (struct hdhomerun_debug_message_t *)malloc(sizeof(struct hdhomerun_debug_message_t)); if (!message) { return; } char *ptr = message->buffer; char *end = message->buffer + sizeof(message->buffer) - 2; *end = 0; /* * Timestamp. */ time_t current_time = time(NULL); ptr += strftime(ptr, end - ptr, "%Y%m%d-%H:%M:%S ", localtime(¤t_time)); if (ptr > end) { ptr = end; } /* * Debug prefix. */ pthread_mutex_lock(&dbg->print_lock); if (dbg->prefix) { hdhomerun_sprintf(ptr, end, "%s ", dbg->prefix); ptr = strchr(ptr, 0); } pthread_mutex_unlock(&dbg->print_lock); /* * Message text. */ hdhomerun_vsprintf(ptr, end, fmt, args); ptr = strchr(ptr, 0); /* * Force newline. */ if (ptr[-1] != '\n') { hdhomerun_sprintf(ptr, end, "\n"); } /* * Enqueue. */ pthread_mutex_lock(&dbg->queue_lock); message->prev = NULL; message->next = dbg->queue_head; dbg->queue_head = message; if (message->next) { message->next->prev = message; } else { dbg->queue_tail = message; } dbg->queue_depth++; pthread_mutex_unlock(&dbg->queue_lock); }