static block_t *Read (access_t *access) { #define BUFSIZE (20*188) block_t *block = block_Alloc (BUFSIZE); if (unlikely(block == NULL)) return NULL; access_sys_t *sys = access->p_sys; ssize_t val = dvb_read (sys->dev, block->p_buffer, BUFSIZE); if (val <= 0) { if (val == 0) access->info.b_eof = true; block_Release (block); return NULL; } block->i_buffer = val; /* Fetch the signal levels every so often. Some devices do not like this * to be requested too frequently, e.g. due to low bandwidth I²C bus. */ if ((sys->signal_poll++) == 0) access->info.i_update |= INPUT_UPDATE_SIGNAL; return block; }
static block_t *Read (access_t *access) { #define BUFSIZE (20*188) block_t *block = block_Alloc (BUFSIZE); if (unlikely(block == NULL)) return NULL; access_sys_t *sys = access->p_sys; ssize_t val = dvb_read (sys->dev, block->p_buffer, BUFSIZE); if (val <= 0) { if (val == 0) access->info.b_eof = true; block_Release (block); return NULL; } block->i_buffer = val; return block; }
/* Program start. */ int main (int argc, char *argv[]) { int crc_dvb = 1, crc_internal = 1, dvb_adapter = 0, dvb_demux = 0, dvb_loop = 1, loop_time = 10; int ch, dvb_demux_fd, dvb_bytes, retval, dvb_data_length = 0, processed_bytes = 0, done = 0, show_bouquet_list = 0, show_sdt_list = 0, show_filtered_list = 0; int filter_bouquet_id = 0, dvbs = 1, hd = 0, filter_user_number = 0; unsigned char filter_region_count = 0; unsigned char filter_region[10]; time_t dvb_loop_start; char dvb_buffer[DVB_BUFFER_SIZE]; char *dvb_data = NULL, *dvb_temp = NULL; Network *network; Transport *transport; Bouquet *bouquet; Service *service; OpenTVChannel *channel; /* Process command line options. */ while ((ch = getopt(argc, argv, "c:C:a:d:l:ib:BSFhvr:s:HU:")) != -1) { switch (ch) { case 'c': crc_dvb = atoi(optarg); slowlane_log(3, "crc_dvb set to %i.", crc_dvb); break; crc_internal = atoi(optarg); slowlane_log(3, "crc_internal set to %i.", crc_internal); break; case 'a': dvb_adapter = atoi(optarg); slowlane_log(3, "dvb_adapter set to %i.", dvb_adapter); break; case 'd': dvb_demux = atoi(optarg); slowlane_log(3, "dvb_demux set to %i.", dvb_demux); break; case 'v': verbose++; slowlane_log(0, "verbose set to %i.", verbose); break; case 'l': loop_time = atoi(optarg); slowlane_log(3, "loop_time set to %i.", loop_time); break; case 'B': show_bouquet_list = 1; slowlane_log(3, "show_bouquet_list set to %i.", show_bouquet_list); break; case 'S': show_sdt_list = 1; slowlane_log(3, "show_sdt_list set to %i.", show_sdt_list); break; case 'b': filter_bouquet_id = atoi(optarg); slowlane_log(3, "filter_bouquet_id to %i.", filter_bouquet_id); break; case 'r': if (filter_region_count == 10) { slowlane_log(1, "filter_region table is full at %i.", filter_region_count); } else { filter_region[filter_region_count] = atoi(optarg); slowlane_log(1, "filter_region table added %i to pos %i.", filter_region[filter_region_count], filter_region_count); filter_region_count++; } break; case 's': dvbs = atoi(optarg); slowlane_log(1, "DVB-S%i and below transports enabled.", dvbs); break; case 'H': hd = 1; slowlane_log(1, "HD transports enabled (%i).", hd); break; case 'F': show_filtered_list = 1; slowlane_log(3, "show_filtered_list set to %i.", show_filtered_list); break; case 'U': filter_user_number = atoi(optarg); slowlane_log(1, "Filtering user numbers above %i.", filter_user_number); break; case 'h': default: usage(); return EXIT_FAILURE; break; } } /* Fetch fd for DVB card. */ if ((dvb_demux_fd = dvb_open(dvb_adapter, dvb_demux)) < 1) { slowlane_log(0, "dvb_open failed and returned %i.", dvb_demux_fd); return EXIT_FAILURE; } /* Set filter for NIT. */ if ((retval = dvb_set_filter(dvb_demux_fd, 0x0010, 0x40, 0xf0, crc_dvb)) < 0) { slowlane_log(0, "NIT dvb_set_filter failed and returned %i.", retval); return EXIT_FAILURE; } /* Record when we start this loop.*/ dvb_loop_start = time(NULL); /* Loop obtaining packets until we have enough. */ while (dvb_loop) { /* Read DVB card. */ if ((dvb_bytes = dvb_read(dvb_demux_fd, dvb_buffer, DVB_BUFFER_SIZE)) <= 0) { slowlane_log(0, "dvb_read failed and returned %i.", dvb_bytes); dvb_close(dvb_demux_fd); return EXIT_FAILURE; } /* Copy data into dvb_data. */ if (dvb_data == NULL) { slowlane_log(3, "dvb_read read in %i, mallocing memory.", dvb_bytes); dvb_data_length = dvb_bytes; dvb_data = (char *) malloc (dvb_data_length); memcpy(dvb_data, dvb_buffer, dvb_data_length); } else { slowlane_log(3, "dvb_read read in %i, already %i here, reallocing memory.", dvb_bytes, dvb_data_length); dvb_data = (char *) realloc (dvb_data, dvb_data_length + dvb_bytes); memcpy(dvb_data + dvb_data_length, dvb_buffer, dvb_bytes); dvb_data_length += dvb_bytes; } /* Loop while processing function is reporting success, this is needed for some dvb cards or sasc-ng virtual cards which * don't obey the one packet per read rule. */ do { /* Process SI received. */ if ((processed_bytes = si_process((unsigned char *)dvb_data, dvb_data_length, crc_internal)) < 0) { slowlane_log(0, "si_process failed and returned %i.", processed_bytes); /* Dump data and flush buffer. */ free(dvb_data); dvb_data = NULL; dvb_data_length = 0; } else { if (processed_bytes > 0) { if (processed_bytes == dvb_data_length) { slowlane_log(3, "si_process processed whole data of size %i.", processed_bytes); dvb_data_length = 0; free(dvb_data); dvb_data = NULL; } else { slowlane_log(3, "si_process processed less then whole data of size %i out of %i.", processed_bytes, dvb_data_length); dvb_temp = (char *) malloc (dvb_data_length - processed_bytes); memcpy(dvb_temp, dvb_data + processed_bytes, dvb_data_length - processed_bytes); free(dvb_data); dvb_data = dvb_temp; dvb_data_length -= processed_bytes; } } } } while (processed_bytes < dvb_data_length && processed_bytes > 0); if (dvb_loop == 1) { /* Verify if timeout has expired. */ if (time(NULL) > dvb_loop_start + loop_time) { /* Verify if all present networks are complete. */ done = 1; for (network = network_list; network != NULL; network = network->next) { if (!section_tracking_check(&network->sections)) { done = 0; } } if (done) { /* Inform the user. */ slowlane_log(2, "NIT tables complete (%i), moving to BAT and DST tables.", dvb_loop); /* Set filter for BAT and SDT. */ if ((retval = dvb_set_filter(dvb_demux_fd, 0x0011, 0x40, 0xf0, crc_dvb)) < 0) { slowlane_log(0, "BAT/DST dvb_set_filter failed and returned %i.", retval); return EXIT_FAILURE; } /* Essentially starting the loop again. */ dvb_loop_start = time(NULL); dvb_loop = 2; } } } else { /* Verify if timeout has expired. */ if (time(NULL) > dvb_loop_start + loop_time) { /* Verify if all present networks are complete. */ done = 1; for (network = network_list; network != NULL; network = network->next) { for (transport = network->transports; transport != NULL; transport = transport->next) { if (transport->sections.populated == 0 || !section_tracking_check(&transport->sections)) { done = 0; } } } for (bouquet = bouquet_list; bouquet != NULL; bouquet = bouquet->next) { if (!section_tracking_check(&bouquet->sections)) { done = 0; } } if (done) { /* Inform the user. */ slowlane_log(2, "BAT and DST tables complete (%i).", dvb_loop); dvb_loop = 0; break; } } } } /* Close fd now we're done. */ dvb_close(dvb_demux_fd); /* Print Bouquet List if requested. */ if (show_bouquet_list) { printf("# Bouquet List\n"); for (bouquet = bouquet_list; bouquet != NULL; bouquet = bouquet->next) { printf("%i,%s\n", bouquet->bouquet_id, bouquet->name); } } /* Print Network, Transponder and Service List if requested. */ if (show_sdt_list) { printf("# Satellite Network, Transponder and Service List.\n"); for (network = network_list; network != NULL; network = network->next) { printf("N %i - %s\n", network->network_id, network->name); for (transport = network->transports; transport != NULL; transport = transport->next) { printf("T %i - ON: %i ModSys: %i Freq: %i Sym: %i Pol: %i ModType: %i FEC: %i RollOff: %i Orb: %i West: %i\n", transport->transport_id, transport->original_network_id, transport->modulation_system, transport->frequency, transport->symbol_rate, transport->polarization, transport->modulation_type, transport->fec, transport->roll_off, transport->orbital_position, transport->west_east_flag); for (service = transport->services; service != NULL; service = service->next) { printf("S %i - Running: %i FreeCA: %i Type: %i Name: %s AltName: %s Provider: %s\n", service->service_id, service->running, service->free_ca, service->type, service->name, service->alt_name, service->provider); } } } } /* If we did either of the above, abort. */ if (show_bouquet_list || show_sdt_list) { return EXIT_SUCCESS; } /* Process BAT/SMT data to form channnel list. */ bouquet = filter_data (filter_bouquet_id, filter_region_count, filter_region, dvbs, hd, filter_user_number); /* Exit if we're displaying the list. */ if (show_filtered_list) { /* Cycle through channels. */ for (channel = bouquet->channels; channel != NULL; channel = channel->next) { printf("O (%i:%i) %i %s (%s)\n", channel->transport->transport_id, channel->service->service_id, channel->user_number, channel->service->name, channel->service->alt_name); } return EXIT_SUCCESS; } /* XXX - Update MySQL database with it. */ for (channel = bouquet->channels; channel != NULL; channel = channel->next) { printf("%i,%i,%i,%i,%i,%i,%i,%i,%i,%s\n", channel->transport->transport_id, channel->transport->original_network_id, channel->transport->frequency, channel->transport->symbol_rate, channel->transport->polarization, channel->transport->modulation_system, channel->transport->roll_off, channel->service->service_id, channel->user_number, channel->service->name ); } /* XXX - Somehow handle xmltv overrides. */ return EXIT_SUCCESS; }
void download_opentv () { int i; dvb_t settings; char dictionary[256]; interactive_send (ACTION_START); log_add ("Started OpenTV events download"); sprintf (dictionary, "%s/providers/%s.dict", homedir, provider); opentv_init (); if (huffman_read_dictionary (dictionary)) { char size[256]; settings.pids = providers_get_channels_pids (); settings.pids_count = providers_get_channels_pids_count (); settings.demuxer = demuxer; settings.min_length = 11; settings.buffer_size = 16 * 1024; settings.filter = 0x4a; settings.mask = 0xff; log_add ("Reading channels..."); interactive_send_text (ACTION_TYPE, "READ CHANNELS"); dvb_read (&settings, *bat_callback); log_add ("Read %d channels", opentv_channels_count ()); if (stop) goto opentv_stop; settings.pids = providers_get_titles_pids (); settings.pids_count = providers_get_titles_pids_count (); settings.demuxer = demuxer; settings.min_length = 20; settings.buffer_size = 16 * 1024; settings.filter = 0xa0; settings.mask = 0xfc; buffer_index = 0; buffer_size = 0; buffer_size_last = 0; log_add ("Reading titles..."); interactive_send_text (ACTION_TYPE, "READ TITLES"); dvb_read (&settings, *opentv_titles_callback); format_size (size, buffer_size); log_add ("Read %s", size); interactive_send_text (ACTION_SIZE, size); if (stop) goto opentv_stop; log_add ("Parsing titles..."); interactive_send_text (ACTION_TYPE, "PARSE TITLES"); interactive_send_text (ACTION_PROGRESS, "ON"); buffer_size = 0; time_t lasttime = 0; for (i=0; i<buffer_index; i++) { if (!stop) opentv_read_titles (buffer[i].data, buffer[i].size, huffman_debug_titles); buffer_size += buffer[i].size; _free (buffer[i].data); if ((i % 100) == 0) { if (lasttime != time (NULL) || (i == buffer_index-1)) { lasttime = time (NULL); format_size (size, buffer_size); interactive_send_text (ACTION_SIZE, size); interactive_send_int (ACTION_PROGRESS, (i*100)/buffer_index); } } } format_size (size, buffer_size); interactive_send_text (ACTION_SIZE, size); log_add ("Titles parsed"); interactive_send_text (ACTION_PROGRESS, "OFF"); if (stop) goto opentv_stop; settings.pids = providers_get_summaries_pids (); settings.pids_count = providers_get_summaries_pids_count (); settings.demuxer = demuxer; settings.min_length = 20; settings.buffer_size = 16 * 1024; settings.filter = 0xa8; settings.mask = 0xfc; buffer_index = 0; buffer_size = 0; buffer_size_last = 0; log_add ("Reading summaries..."); interactive_send_text (ACTION_TYPE, "READ SUMMARIES"); dvb_read (&settings, *opentv_summaries_callback); format_size (size, buffer_size); log_add ("Read %s", size); interactive_send_text (ACTION_SIZE, size); if (stop) goto opentv_stop; log_add ("Parsing summaries..."); interactive_send_text (ACTION_TYPE, "PARSE SUMMARIES"); interactive_send_text (ACTION_PROGRESS, "ON"); buffer_size = 0; lasttime = 0; for (i=0; i<buffer_index; i++) { if (!stop) opentv_read_summaries (buffer[i].data, buffer[i].size, huffman_debug_summaries); buffer_size += buffer[i].size; _free (buffer[i].data); if ((i % 100) == 0) { if (lasttime != time (NULL) || (i == buffer_index-1)) { lasttime = time (NULL); format_size (size, buffer_size); interactive_send_text (ACTION_SIZE, size); interactive_send_int (ACTION_PROGRESS, (i*100)/buffer_index); } } } format_size (size, buffer_size); interactive_send_text (ACTION_SIZE, size); log_add ("Summaries parsed"); interactive_send_text (ACTION_PROGRESS, "OFF"); //if (stop) goto opentv_stop; opentv_stop: huffman_free_dictionary (); } exec = false; opentv_cleanup (); interactive_send (ACTION_END); log_add ("Ended OpenTV events download"); }