summaryrefslogtreecommitdiff
path: root/src/input/input_dvb.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/input/input_dvb.c')
-rw-r--r--src/input/input_dvb.c456
1 files changed, 247 insertions, 209 deletions
diff --git a/src/input/input_dvb.c b/src/input/input_dvb.c
index 10d6eca55..07aefc362 100644
--- a/src/input/input_dvb.c
+++ b/src/input/input_dvb.c
@@ -15,7 +15,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
*
*
* Input plugin for Digital TV (Digital Video Broadcast - DVB) devices,
@@ -27,7 +27,7 @@
* Date Author
* ---- ------
*
- * 01-Feb-2005 Pekka Jääskeläinen <poj@iki.fi>
+ * 01-Feb-2005 Pekka Jääskeläinen <poj@iki.fi>
*
* - This history log started.
* - Disabled the automatic EPG updater thread until EPG demuxer
@@ -66,17 +66,22 @@
* OSD - this will allow for filtering/searching of epg data - useful for automatic recording :)
*/
-/* pthread.h must be included first so rest of the headers are imported
- thread safely (on some systems). */
-#include <pthread.h>
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
+/* pthread.h must be included first so rest of the headers are imported
+ thread safely (on some systems).
+ However, including it before config.h causes problems with asprintf not
+ being declared (glibc 2.3.6)
+*/
+#include <pthread.h>
+
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
@@ -95,24 +100,27 @@
#endif
#include <ctype.h>
-/* These will eventually be #include <linux/dvb/...> */
-#include "dvb/dmx.h"
-#include "dvb/frontend.h"
+/* XDG */
+#include <basedir.h>
+
+#include <linux/dvb/dmx.h>
+#include <linux/dvb/frontend.h>
#define LOG_MODULE "input_dvb"
#define LOG_VERBOSE
/*
#define LOG
+#define LOG_READS
*/
-#include "xine_internal.h"
-#include "xineutils.h"
-#include "input_plugin.h"
+#include <xine/xine_internal.h>
+#include <xine/xineutils.h>
+#include <xine/input_plugin.h>
#include "net_buf_ctrl.h"
#define BUFSIZE 16384
-#define NOPID 0xffff
+#define DVB_NOPID 0xffff
/* define stream types
* administrative/system PIDs first */
@@ -226,9 +234,8 @@ typedef struct {
int adapter_num;
- char frontend_device[100];
- char dvr_device[100];
- char demux_device[100];
+ char *dvr_device;
+ char *demux_device;
struct dmx_pes_filter_params pesFilterParams[MAX_FILTERS];
struct dmx_pes_filter_params subFilterParams[MAX_SUBTITLES];
@@ -283,7 +290,7 @@ typedef struct {
xine_t *xine;
- char *mrls[5];
+ const char *mrls[5];
int numchannels;
@@ -322,12 +329,12 @@ typedef struct {
osd_object_t *background;
xine_event_queue_t *event_queue;
- /* CRC table for PAT rebuilding */
- unsigned long crc32_table[256];
/* scratch buffer for forward seeking */
char seek_buf[BUFSIZE];
+ /* Is the GUI enabled at all? */
+ int dvb_gui_enabled;
/* simple vcr-like functionality */
int record_fd;
int record_paused;
@@ -351,7 +358,7 @@ typedef struct {
} dvb_input_plugin_t;
typedef struct {
- char *name;
+ const char *name;
int value;
} Param;
@@ -424,7 +431,7 @@ static const Param transmissionmode_list [] = {
};
-time_t dvb_mjdtime (char *buf);
+static time_t dvb_mjdtime (uint8_t *buf);
static void load_epg_data(dvb_input_plugin_t *this);
static void show_eit(dvb_input_plugin_t *this);
@@ -440,28 +447,6 @@ static void print_info(const char* estring) {
}
#endif
-static void ts_build_crc32_table(dvb_input_plugin_t *this) {
- uint32_t i, j, k;
-
- for( i = 0 ; i < 256 ; i++ ) {
- k = 0;
- for (j = (i << 24) | 0x800000 ; j != 0x80000000 ; j <<= 1) {
- k = (k << 1) ^ (((k ^ j) & 0x80000000) ? 0x04c11db7 : 0);
- }
- this->crc32_table[i] = k;
- }
-}
-
-static uint32_t ts_compute_crc32(dvb_input_plugin_t *this, uint8_t *data,
- uint32_t length, uint32_t crc32) {
- uint32_t i;
-
- for(i = 0; i < length; i++) {
- crc32 = (crc32 << 8) ^ this->crc32_table[(crc32 >> 24) ^ data[i]];
- }
- return crc32;
-}
-
static unsigned int getbits(unsigned char *buffer, unsigned int bitpos, unsigned int bitcount)
{
@@ -505,7 +490,7 @@ static int find_descriptor(uint8_t tag, const unsigned char *buf, int descriptor
/* Extract UTC time and date encoded in modified julian date format and return it as a time_t.
*/
-time_t dvb_mjdtime (char *buf)
+static time_t dvb_mjdtime (uint8_t *buf)
{
int i;
unsigned int year, month, day, hour, min, sec;
@@ -562,9 +547,10 @@ static void tuner_dispose(tuner_t * this)
for (x = 0; x < MAX_SUBTITLES; x++)
if (this->fd_subfilter[x] >= 0)
close(this->fd_subfilter[x]);
-
- if(this)
- free(this);
+
+ free(this->dvr_device);
+ free(this->demux_device);
+ free(this);
}
@@ -574,14 +560,14 @@ static tuner_t *tuner_init(xine_t * xine, int adapter)
tuner_t *this;
int x;
int test_video;
- char *video_device=xine_xmalloc(200);
+ char *video_device = NULL;
+ char *frontend_device = NULL;
- _x_assert(video_device != NULL);
-
this = (tuner_t *) xine_xmalloc(sizeof(tuner_t));
_x_assert(this != NULL);
-
+
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG, "tuner_init adapter=%d\n", adapter);
this->fd_frontend = -1;
for (x = 0; x < MAX_FILTERS; x++)
this->fd_pidfilter[x] = 0;
@@ -589,21 +575,24 @@ static tuner_t *tuner_init(xine_t * xine, int adapter)
this->xine = xine;
this->adapter_num = adapter;
- snprintf(this->frontend_device,100,"/dev/dvb/adapter%i/frontend0",this->adapter_num);
- snprintf(this->demux_device,100,"/dev/dvb/adapter%i/demux0",this->adapter_num);
- snprintf(this->dvr_device,100,"/dev/dvb/adapter%i/dvr0",this->adapter_num);
- snprintf(video_device,100,"/dev/dvb/adapter%i/video0",this->adapter_num);
-
- if ((this->fd_frontend = open(this->frontend_device, O_RDWR)) < 0) {
+ asprintf(&this->demux_device,"/dev/dvb/adapter%i/demux0",this->adapter_num);
+ asprintf(&this->dvr_device,"/dev/dvb/adapter%i/dvr0",this->adapter_num);
+ asprintf(&video_device,"/dev/dvb/adapter%i/video0",this->adapter_num);
+
+ asprintf(&frontend_device,"/dev/dvb/adapter%i/frontend0",this->adapter_num);
+ if ((this->fd_frontend = open(frontend_device, O_RDWR)) < 0) {
xprintf(this->xine, XINE_VERBOSITY_DEBUG, "FRONTEND DEVICE: %s\n", strerror(errno));
tuner_dispose(this);
- return NULL;
+ this = NULL;
+ goto exit;
}
+ free(frontend_device); frontend_device = NULL;
if ((ioctl(this->fd_frontend, FE_GET_INFO, &this->feinfo)) < 0) {
xprintf(this->xine, XINE_VERBOSITY_DEBUG, "FE_GET_INFO: %s\n", strerror(errno));
tuner_dispose(this);
- return NULL;
+ this = NULL;
+ goto exit;
}
for (x = 0; x < MAX_FILTERS; x++) {
@@ -611,7 +600,8 @@ static tuner_t *tuner_init(xine_t * xine, int adapter)
if (this->fd_pidfilter[x] < 0) {
xprintf(this->xine, XINE_VERBOSITY_DEBUG, "DEMUX DEVICE PIDfilter: %s\n", strerror(errno));
tuner_dispose(this);
- return NULL;
+ this = NULL;
+ goto exit;
}
}
for (x = 0; x < MAX_SUBTITLES; x++) {
@@ -626,7 +616,7 @@ static tuner_t *tuner_init(xine_t * xine, int adapter)
xprintf(this->xine,XINE_VERBOSITY_DEBUG,"input_dvb: couldn't set EIT to nonblock: %s\n",strerror(errno));
/* and the internal filter used for PAT & PMT */
if(fcntl(this->fd_pidfilter[INTERNAL_FILTER], F_SETFL, O_NONBLOCK)<0)
- xprintf(this->xine,XINE_VERBOSITY_DEBUG,"input_dvb: couldn't set EIT to nonblock: %s\n",strerror(errno));
+ xprintf(this->xine,XINE_VERBOSITY_DEBUG,"input_dvb: couldn't set INTERNAL to nonblock: %s\n",strerror(errno));
/* and the frontend */
fcntl(this->fd_frontend, F_SETFL, O_NONBLOCK);
@@ -643,7 +633,9 @@ static tuner_t *tuner_init(xine_t * xine, int adapter)
close(test_video);
}
+ exit:
free(video_device);
+ free(frontend_device);
return this;
}
@@ -653,7 +645,7 @@ static int dvb_set_pidfilter(dvb_input_plugin_t * this, int filter, ushort pid,
{
tuner_t *tuner = this->tuner;
- if(this->channels[this->channel].pid [filter] !=NOPID) {
+ if(this->channels[this->channel].pid [filter] !=DVB_NOPID) {
ioctl(tuner->fd_pidfilter[filter], DMX_STOP);
}
@@ -676,7 +668,7 @@ static int dvb_set_sectfilter(dvb_input_plugin_t * this, int filter, ushort pid,
{
tuner_t *tuner = this->tuner;
- if(this->channels[this->channel].pid [filter] !=NOPID) {
+ if(this->channels[this->channel].pid [filter] !=DVB_NOPID) {
ioctl(tuner->fd_pidfilter[filter], DMX_STOP);
}
@@ -703,7 +695,7 @@ static int find_param(const Param *list, const char *name)
return list->value;;
}
-static int extract_channel_from_string(channel_t * channel,char * str,fe_type_t fe_type)
+static int extract_channel_from_string_internal(channel_t * channel,char * str,fe_type_t fe_type)
{
/*
try to extract channel data from a string in the following format
@@ -864,55 +856,69 @@ static int extract_channel_from_string(channel_t * channel,char * str,fe_type_t
return 0;
}
-static channel_t *load_channels(dvb_input_plugin_t *this, int *num_ch, fe_type_t fe_type) {
+static int extract_channel_from_string(channel_t *channel, char *str, fe_type_t fe_type)
+{
+ channel->name = NULL;
+ if (!extract_channel_from_string_internal(channel, str, fe_type))
+ return 0;
+ free (channel->name); /* without this, we have a possible memleak */
+ return -1;
+}
+
+static channel_t *load_channels(xine_t *xine, xine_stream_t *stream, int *num_ch, fe_type_t fe_type) {
FILE *f;
char str[BUFSIZE];
char filename[BUFSIZE];
- channel_t *channels;
- int num_channels;
+ channel_t *channels = NULL;
+ int num_channels = 0;
+ int num_alloc = 0;
int i;
- xine_t *xine = this->class->xine;
-
- snprintf(filename, BUFSIZE, "%s/.xine/channels.conf", xine_get_homedir());
+ struct stat st;
- f = fopen(filename, "rb");
+ snprintf(filename, BUFSIZE, "%s/"PACKAGE"/channels.conf", xdgConfigHome(xine->basedir_handle));
+
+ f = fopen(filename, "r");
if (!f) {
- xprintf(xine, XINE_VERBOSITY_LOG, _("input_dvb: failed to open dvb channel file '%s'\n"), filename);
- _x_message(this->stream, XINE_MSG_FILE_NOT_FOUND, filename, "Please run the dvbscan utility.", NULL);
+ xprintf(xine, XINE_VERBOSITY_LOG, _("input_dvb: failed to open dvb channel file '%s': %s\n"), filename, strerror (errno));
+ if (!f && stream)
+ _x_message(stream, XINE_MSG_FILE_NOT_FOUND, filename, "Please run the dvbscan utility.", NULL);
return NULL;
}
-
- /*
- * count and alloc channels
- */
- num_channels = 0;
- while ( fgets (str, BUFSIZE, f)) {
- num_channels++;
- }
- fclose (f);
-
- if(num_channels > 0)
- xprintf (xine, XINE_VERBOSITY_DEBUG, "input_dvb: expecting %d channels...\n", num_channels);
- else {
- xprintf (xine, XINE_VERBOSITY_DEBUG, "input_dvb: no channels found in the file: giving up.\n");
+ if (fstat(fileno(f), &st) || !S_ISREG (st.st_mode)) {
+ xprintf(xine, XINE_VERBOSITY_LOG, _("input_dvb: dvb channel file '%s' is not a plain file\n"), filename);
+ fclose(f);
return NULL;
}
- channels = xine_xmalloc (sizeof (channel_t) * num_channels);
-
- _x_assert(channels != NULL);
-
/*
* load channel list
*/
- f = fopen (filename, "rb");
- num_channels = 0;
while ( fgets (str, BUFSIZE, f)) {
- if (extract_channel_from_string(&(channels[num_channels]),str,fe_type) < 0)
+ channel_t channel = {0};
+
+ /* lose trailing spaces & control characters */
+ i = strlen (str);
+ while (i && str[i - 1] <= ' ')
+ --i;
+ if (i == 0)
+ continue;
+ str[i] = 0;
+
+ if (extract_channel_from_string(&channel,str,fe_type) < 0)
continue;
+ if (num_channels >= num_alloc) {
+ channel_t *new_channels = xine_xmalloc((num_alloc += 32) * sizeof (channel_t));
+ _x_assert(new_channels != NULL);
+ memcpy(new_channels, channels, num_channels * sizeof (channel_t));
+ free(channels);
+ channels = new_channels;
+ }
+
+ channels[num_channels] = channel;
+
/* Initially there's no EPG data in the EPG structs. */
channels[num_channels].epg_count = 0;
for (i = 0; i < MAX_EPG_ENTRIES_PER_CHANNEL; ++i)
@@ -922,6 +928,9 @@ static channel_t *load_channels(dvb_input_plugin_t *this, int *num_ch, fe_type_t
}
fclose(f);
+ /* free any trailing unused entries */
+ channels = realloc (channels, num_channels * sizeof (channel_t));
+
if(num_channels > 0)
xprintf (xine, XINE_VERBOSITY_DEBUG, "input_dvb: found %d channels...\n", num_channels);
else {
@@ -934,6 +943,14 @@ static channel_t *load_channels(dvb_input_plugin_t *this, int *num_ch, fe_type_t
return channels;
}
+static void free_channel_list (channel_t *channels, int num_channels)
+{
+ if (channels)
+ while (--num_channels >= 0)
+ free(channels[num_channels].name);
+ free(channels);
+}
+
static int tuner_set_diseqc(tuner_t *this, channel_t *c)
{
struct dvb_diseqc_master_cmd cmd =
@@ -972,12 +989,15 @@ static int tuner_tune_it (tuner_t *this, struct dvb_frontend_parameters
struct dvb_frontend_event event;
unsigned int strength;
struct pollfd pfd[1];
+ xine_cfg_entry_t config_tuning_timeout;
+ struct timeval time_now;
+ struct timeval tuning_timeout;
/* discard stale events */
while (ioctl(this->fd_frontend, FE_GET_EVENT, &event) != -1);
if (ioctl(this->fd_frontend, FE_SET_FRONTEND, front_param) <0) {
- xprintf(this->xine, XINE_VERBOSITY_DEBUG, "setfront front: %s\n", strerror(errno));
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG, "input_dvb: setfront front: %s\n", strerror(errno));
return 0;
}
@@ -999,11 +1019,24 @@ static int tuner_tune_it (tuner_t *this, struct dvb_frontend_parameters
return 0;
}
}
+
+ xine_config_lookup_entry(this->xine, "media.dvb.tuning_timeout", &config_tuning_timeout);
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG, "input_dvb: media.dvb.tuning_timeout is %d\n", config_tuning_timeout.num_value );
+
+ if( config_tuning_timeout.num_value != 0 ) {
+ gettimeofday( &tuning_timeout, NULL );
+ if( config_tuning_timeout.num_value < 5 )
+ tuning_timeout.tv_sec += 5;
+ else
+ tuning_timeout.tv_sec += config_tuning_timeout.num_value;
+ }
+
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG, "input_dvb: tuner_tune_it - waiting for lock...\n" );
do {
status = 0;
if (ioctl(this->fd_frontend, FE_READ_STATUS, &status) < 0) {
- xprintf(this->xine, XINE_VERBOSITY_DEBUG, "fe get event: %s\n", strerror(errno));
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG, "input_dvb: fe get event: %s\n", strerror(errno));
return 0;
}
@@ -1011,8 +1044,20 @@ static int tuner_tune_it (tuner_t *this, struct dvb_frontend_parameters
if (status & FE_HAS_LOCK) {
break;
}
- usleep(500000);
- print_error("Trying to get lock...");
+
+ /* FE_TIMEDOUT does not happen in a no signal condition.
+ * Use the tuning_timeout config to prevent a hang in this loop
+ */
+ if( config_tuning_timeout.num_value != 0 ) {
+ gettimeofday( &time_now, NULL );
+ if( time_now.tv_sec > tuning_timeout.tv_sec ) {
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG, "input_dvb: No FE_HAS_LOCK before timeout\n");
+ break;
+ }
+ }
+
+ usleep(10000);
+ xprintf(this->xine, XINE_VERBOSITY_DEBUG, "Trying to get lock...");
} while (!(status & FE_TIMEDOUT));
/* inform the user of frontend status */
@@ -1119,7 +1164,7 @@ static void parse_pmt(dvb_input_plugin_t *this, const unsigned char *buf, int se
* parsing the descriptor. */
if(has_subs <= MAX_SUBTITLES) {
xprintf(this->stream->xine,XINE_VERBOSITY_LOG,"input_dvb: Adding SUBTITLES: PID 0x%04x\n", elementary_pid);
- if(this->channels[this->channel].subpid [has_subs] !=NOPID) {
+ if(this->channels[this->channel].subpid [has_subs] !=DVB_NOPID) {
ioctl(this->tuner->fd_subfilter[has_subs], DMX_STOP);
}
this->channels[this->channel].subpid [has_subs] = elementary_pid;
@@ -1163,8 +1208,8 @@ static void parse_pmt(dvb_input_plugin_t *this, const unsigned char *buf, int se
static void dvb_parse_si(dvb_input_plugin_t *this) {
- char *tmpbuffer;
- char *bufptr;
+ uint8_t *tmpbuffer;
+ uint8_t *bufptr;
int service_id;
int result;
int section_len;
@@ -1272,8 +1317,8 @@ static void dvb_parse_si(dvb_input_plugin_t *this) {
/* Helper function for finding the channel index in the channels struct
given the service_id. If channel is not found, -1 is returned. */
-static int channel_index(dvb_input_plugin_t* this, unsigned int service_id) {
- unsigned int n;
+static int channel_index(dvb_input_plugin_t* this, int service_id) {
+ int n;
for (n=0; n < this->num_channels; n++)
if (this->channels[n].service_id == service_id)
return n;
@@ -1363,8 +1408,8 @@ static void load_epg_data(dvb_input_plugin_t *this)
int section_len = 0;
unsigned int service_id=-1;
int n;
- char *eit = NULL;
- char *foo = NULL;
+ uint8_t *eit = NULL;
+ uint8_t *foo = NULL;
char *seen_channels = NULL;
int text_len;
struct pollfd fd;
@@ -1551,7 +1596,7 @@ static void load_epg_data(dvb_input_plugin_t *this)
case 0x54: { /* Content Descriptor, riveting stuff */
int content_bits = getbits(eit, 8, 4);
- char *content[] = {
+ static const char *const content[] = {
"UNKNOWN","MOVIE","NEWS","ENTERTAINMENT","SPORT",
"CHILDRENS","MUSIC","ARTS/CULTURE","CURRENT AFFAIRS",
"EDUCATIONAL","INFOTAINMENT","SPECIAL","COMEDY","DRAMA",
@@ -2416,7 +2461,7 @@ static void ts_rewrite_packets (dvb_input_plugin_t *this, unsigned char * origin
originalPkt[11]=(this->channels[this->channel].pmtpid >> 8) & 0xff;
originalPkt[12]=this->channels[this->channel].pmtpid & 0xff;
- crc= ts_compute_crc32 (this, originalPkt+1, 12, 0xffffffff);
+ crc= _x_compute_crc32 (originalPkt+1, 12, 0xffffffff);
originalPkt[13]=(crc>>24) & 0xff;
originalPkt[14]=(crc>>16) & 0xff;
@@ -2434,21 +2479,23 @@ static void ts_rewrite_packets (dvb_input_plugin_t *this, unsigned char * origin
}
static off_t dvb_plugin_read (input_plugin_t *this_gen,
- char *buf, off_t len) {
+ void *buf_gen, off_t len) {
dvb_input_plugin_t *this = (dvb_input_plugin_t *) this_gen;
+ uint8_t *buf = buf_gen;
+
off_t n=0, total=0;
int have_mutex=0;
struct pollfd pfd;
if (!this->tuned_in)
return 0;
- dvb_event_handler (this);
+ if (this->dvb_gui_enabled)
+ dvb_event_handler (this);
+#ifdef LOG_READS
xprintf(this->class->xine,XINE_VERBOSITY_DEBUG,
"input_dvb: reading %" PRIdMAX " bytes...\n", (intmax_t)len);
-
-#ifndef DVB_NO_BUFFERING
- nbc_check_buffers (this->nbc);
#endif
+
/* protect against channel changes */
have_mutex = pthread_mutex_lock(&this->channel_change_mutex);
total=0;
@@ -2496,9 +2543,11 @@ static off_t dvb_plugin_read (input_plugin_t *this_gen,
break;
}
+#ifdef LOG_READS
xprintf(this->class->xine,XINE_VERBOSITY_DEBUG,
"input_dvb: got %" PRIdMAX " bytes (%" PRIdMAX "/%" PRIdMAX " bytes read)\n",
(intmax_t)n, (intmax_t)total, (intmax_t)len);
+#endif
if (n > 0){
this->curpos += n;
@@ -2624,7 +2673,7 @@ static void dvb_plugin_dispose (input_plugin_t *this_gen) {
}
}
if (this->channels)
- free (this->channels);
+ free_channel_list (this->channels, this->num_channels);
/* Make the EPG updater thread return. */
@@ -2703,6 +2752,11 @@ static int dvb_plugin_open(input_plugin_t * this_gen)
xine_cfg_entry_t zoomdvb;
xine_cfg_entry_t adapter;
xine_cfg_entry_t lastchannel;
+ xine_cfg_entry_t gui_enabled;
+
+ xine_config_lookup_entry(this->stream->xine, "media.dvb.gui_enabled", &gui_enabled);
+ this->dvb_gui_enabled = gui_enabled.num_value;
+ xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("input_dvb: DVB GUI %s\n"), this->dvb_gui_enabled ? "enabled" : "disabled");
xine_config_lookup_entry(this->stream->xine, "media.dvb.adapter", &adapter);
@@ -2719,7 +2773,7 @@ static int dvb_plugin_open(input_plugin_t * this_gen)
* and assume that its format is valid for our tuner type
*/
- if (!(channels = load_channels(this, &num_channels, tuner->feinfo.type)))
+ if (!(channels = load_channels(this->class->xine, this->stream, &num_channels, tuner->feinfo.type)))
{
/* failed to load the channels */
tuner_dispose(tuner);
@@ -2762,7 +2816,7 @@ static int dvb_plugin_open(input_plugin_t * this_gen)
* by numbers...
*/
int chanlen = strlen(channame);
- int offset = 0;
+ size_t offset = 0;
xprintf(this->class->xine, XINE_VERBOSITY_LOG,
_("input_dvb: exact match for %s not found: trying partial matches\n"), channame);
@@ -2779,7 +2833,7 @@ static int dvb_plugin_open(input_plugin_t * this_gen)
idx++;
}
offset++;
- xprintf(this->class->xine,XINE_VERBOSITY_LOG,"%d,%d,%d\n", offset, idx, num_channels);
+ xprintf(this->class->xine,XINE_VERBOSITY_LOG,"%zd,%d,%d\n", offset, idx, num_channels);
}
while ((offset < 6) && (idx == num_channels));
if (idx < num_channels) {
@@ -2872,13 +2926,13 @@ static int dvb_plugin_open(input_plugin_t * this_gen)
{
fprintf(stderr,"input_dvb: 2a %x\n",tuner->feinfo.type);
/*
- * This is dvbc://<channel name>:<qam tuning parameters>
+ * This is dvba://<channel name>:<atsc tuning parameters>
*/
if (tuner->feinfo.type != FE_ATSC)
{
fprintf(stderr,"input_dvb: FAILED 1\n");
xprintf(this->class->xine, XINE_VERBOSITY_LOG,
- _("input_dvb: dvbc mrl specified but the tuner doesn't appear to be QAM (DVB-C)\n"));
+ _("input_dvb: dvba mrl specified but the tuner doesn't appear to be ATSC (DVB-A)\n"));
tuner_dispose(tuner);
return 0;
}
@@ -2929,15 +2983,16 @@ static int dvb_plugin_open(input_plugin_t * this_gen)
this->event_queue = xine_event_new_queue(this->stream);
#ifdef EPG_UPDATE_IN_BACKGROUND
- /* Start the EPG updater thread. */
- this->epg_updater_stop = 0;
- if (pthread_create(&this->epg_updater_thread, NULL,
- epg_data_updater, this) != 0) {
- xprintf(
- this->class->xine, XINE_VERBOSITY_LOG,
- _("input_dvb: cannot create EPG updater thread\n"));
- return 0;
-
+ if (this->dvb_gui_enabled) {
+ /* Start the EPG updater thread. */
+ this->epg_updater_stop = 0;
+ if (pthread_create(&this->epg_updater_thread, NULL,
+ epg_data_updater, this) != 0) {
+ xprintf(
+ this->class->xine, XINE_VERBOSITY_LOG,
+ _("input_dvb: cannot create EPG updater thread\n"));
+ return 0;
+ }
}
#endif
/*
@@ -3018,12 +3073,10 @@ static int dvb_plugin_open(input_plugin_t * this_gen)
snprintf(str, 256, "%s", this->channels[this->channel].name);
_x_meta_info_set(this->stream, XINE_META_INFO_TITLE, str);
- /* compute CRC table for rebuilding pat */
- ts_build_crc32_table(this);
/* Clear all pids, the pmt will tell us which to use */
for (x = 0; x < MAX_FILTERS; x++){
- this->channels[this->channel].pid[x] = NOPID;
+ this->channels[this->channel].pid[x] = DVB_NOPID;
}
@@ -3090,15 +3143,6 @@ static input_plugin_t *dvb_class_get_instance (input_class_t *class_gen,
* dvb input plugin class stuff
*/
-static const char *dvb_class_get_description (input_class_t *this_gen) {
- return _("DVB (Digital TV) input plugin");
-}
-
-static const char *dvb_class_get_identifier (input_class_t *this_gen) {
- return "dvb";
-}
-
-
static void dvb_class_dispose(input_class_t * this_gen)
{
dvb_input_class_t *class = (dvb_input_class_t *) this_gen;
@@ -3120,77 +3164,61 @@ static char **dvb_class_get_autoplay_list(input_class_t * this_gen,
{
dvb_input_class_t *class = (dvb_input_class_t *) this_gen;
channel_t *channels=NULL;
- FILE *f;
- char *tmpbuffer=xine_xmalloc(BUFSIZE);
- char *foobuffer=xine_xmalloc(BUFSIZE);
- char *str=tmpbuffer;
- int num_channels;
- int nlines=0;
- int default_channel;
- xine_cfg_entry_t lastchannel_enable;
+ char foobuffer[BUFSIZE];
+ int ch, apch, num_channels = 0;
+ int default_channel = -1;
+ xine_cfg_entry_t lastchannel_enable = {0};
xine_cfg_entry_t lastchannel;
- _x_assert(tmpbuffer != NULL);
- _x_assert(foobuffer != NULL);
-
- snprintf(tmpbuffer, BUFSIZE, "%s/.xine/channels.conf", xine_get_homedir());
-
- num_channels = 0;
-
- f=fopen (tmpbuffer,"rb");
- if(!f){ /* channels.conf not found in .xine */
- class->mrls[0]="Sorry, No channels.conf found";
- class->mrls[1]="Please run the dvbscan utility";
- class->mrls[2]="from the dvb drivers apps package";
- class->mrls[3]="and place the file in ~/.xine/";
- *num_files=4;
- free(tmpbuffer);
- free(foobuffer);
- return class->mrls;
- } else {
- while (fgets(str, BUFSIZE, f))
- nlines++;
- }
- fclose (f);
-
- if (xine_config_lookup_entry(class->xine, "media.dvb.remember_channel", &lastchannel_enable))
- if (lastchannel_enable.num_value){
- num_channels++;
- if (xine_config_lookup_entry(class->xine, "media.dvb.last_channel", &lastchannel))
- default_channel = lastchannel.num_value;
- }
-
- if (nlines+lastchannel_enable.num_value >= MAX_AUTOCHANNELS)
- nlines = MAX_AUTOCHANNELS-lastchannel_enable.num_value;
-
- snprintf(tmpbuffer, BUFSIZE, "%s/.xine/channels.conf", xine_get_homedir());
+ /* need to probe card here to get fe_type to read in channels.conf */
+ tuner_t *tuner;
+ xine_cfg_entry_t adapter;
+ xine_config_lookup_entry(class->xine, "media.dvb.adapter", &adapter);
- f=fopen (tmpbuffer,"rb");
- channels=xine_xmalloc(sizeof(channel_t)*(nlines+lastchannel_enable.num_value));
+ if (!(tuner = tuner_init(class->xine,adapter.num_value))) {
+ xprintf(class->xine, XINE_VERBOSITY_LOG, _("input_dvb: cannot open dvb device\n"));
+ class->mrls[0]="Sorry, No DVB input device found.";
+ *num_files=1;
+ return class->mrls;
+ }
- _x_assert(channels != NULL);
-
+ if (!(channels = load_channels(class->xine, NULL, &num_channels, tuner->feinfo.type))) {
+ /* channels.conf not found in .xine */
+ class->mrls[0]="Sorry, No valid channels.conf found";
+ class->mrls[1]="for the selected DVB device.";
+ class->mrls[2]="Please run the dvbscan utility";
+ class->mrls[3]="from the dvb drivers apps package";
+ class->mrls[4]="and place the file in ~/.xine/";
+ *num_files=5;
+ tuner_dispose(tuner);
+ return class->mrls;
+ }
+
+ tuner_dispose(tuner);
- while (fgets(str,BUFSIZE,f) && num_channels < nlines+lastchannel_enable.num_value) {
- if (extract_channel_from_string (&(channels[num_channels]), str, 0) < 0)
- continue;
-
- sprintf(foobuffer,"dvb://%s",channels[num_channels].name);
- if(class->autoplaylist[num_channels])
- free(class->autoplaylist[num_channels]);
- class->autoplaylist[num_channels]=xine_xmalloc(128);
+ if (xine_config_lookup_entry(class->xine, "media.dvb.remember_channel", &lastchannel_enable)
+ && lastchannel_enable.num_value
+ && xine_config_lookup_entry(class->xine, "media.dvb.last_channel", &lastchannel))
+ {
+ default_channel = lastchannel.num_value - 1;
+ if (default_channel < 0 || default_channel >= num_channels)
+ default_channel = -1;
+ }
- _x_assert(class->autoplaylist[num_channels] != NULL);
-
- class->autoplaylist[num_channels]=strdup(foobuffer);
- num_channels++;
- }
+ for (ch = 0, apch = !!lastchannel_enable.num_value;
+ ch < num_channels && ch < MAX_AUTOCHANNELS;
+ ++ch, ++apch) {
+ snprintf(foobuffer, BUFSIZE, "dvb://%s", channels[ch].name);
+ free(class->autoplaylist[apch]);
+ class->autoplaylist[apch] = strdup(foobuffer);
+ _x_assert(class->autoplaylist[apch] != NULL);
+ }
if (lastchannel_enable.num_value){
- if (lastchannel.num_value > -1 && lastchannel.num_value < num_channels)
+ if (default_channel != -1)
/* plugin has been used before - channel is valid */
- sprintf (foobuffer, "dvb://%s", channels[lastchannel.num_value].name);
+ sprintf (foobuffer, "dvb://%s", channels[default_channel].name);
else
/* set a reasonable default - the first channel */
sprintf (foobuffer, "dvb://%s", num_channels ? channels[0].name : "0");
@@ -3198,13 +3226,10 @@ static char **dvb_class_get_autoplay_list(input_class_t * this_gen,
class->autoplaylist[0]=strdup(foobuffer);
}
- free(tmpbuffer);
- free(foobuffer);
- free(channels);
- fclose(f);
+ free_channel_list(channels, num_channels);
- *num_files = num_channels;
- class->numchannels=nlines;
+ *num_files = num_channels + lastchannel_enable.num_value;
+ class->numchannels = *num_files;
return class->autoplaylist;
}
@@ -3220,8 +3245,8 @@ static void *init_class (xine_t *xine, void *data) {
this->xine = xine;
this->input_class.get_instance = dvb_class_get_instance;
- this->input_class.get_identifier = dvb_class_get_identifier;
- this->input_class.get_description = dvb_class_get_description;
+ this->input_class.identifier = "dvb";
+ this->input_class.description = N_("DVB (Digital TV) input plugin");
this->input_class.get_dir = NULL;
this->input_class.get_autoplay_list = dvb_class_get_autoplay_list;
this->input_class.dispose = dvb_class_dispose;
@@ -3251,6 +3276,19 @@ static void *init_class (xine_t *xine, void *data) {
_("If enabled xine will remember and switch to this channel. "),
21, NULL, NULL);
+ config->register_num(config, "media.dvb.tuning_timeout",
+ 0,
+ _("Number of seconds until tuning times out."),
+ _("Leave at 0 means try forever. "
+ "Greater than 0 means wait that many seconds to get a lock. Minimum is 5 seconds."),
+ 0, NULL, (void *) this);
+
+ /* set to 0 to turn off the GUI built into this input plugin */
+ config->register_bool(config, "media.dvb.gui_enabled",
+ 1,
+ _("Enable the DVB GUI"),
+ _("Enable the DVB GUI, mouse controlled recording and channel switching."),
+ 21, NULL, NULL);
config->register_num(config, "media.dvb.adapter",
0,
@@ -3271,6 +3309,6 @@ static void *init_class (xine_t *xine, void *data) {
const plugin_info_t xine_plugin_info[] EXPORTED = {
/* type, API, "name", version, special_info, init_function */
- { PLUGIN_INPUT | PLUGIN_MUST_PRELOAD, 17, "DVB", XINE_VERSION_CODE, NULL, init_class },
+ { PLUGIN_INPUT | PLUGIN_MUST_PRELOAD, 18, "DVB", XINE_VERSION_CODE, NULL, init_class },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};