summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/input/input_dvb.c244
1 files changed, 184 insertions, 60 deletions
diff --git a/src/input/input_dvb.c b/src/input/input_dvb.c
index 93cada7f8..9c3e75a77 100644
--- a/src/input/input_dvb.c
+++ b/src/input/input_dvb.c
@@ -115,6 +115,22 @@
#define MAX_SUBTITLES 4
+/* Mouse button codes. */
+#define MOUSE_BUTTON_LEFT 1
+#define MOUSE_BUTTON_MIDDLE 2
+#define MOUSE_BUTTON_RIGHT 3
+#define MOUSE_WHEEL_UP 4
+#define MOUSE_WHEEL_DOWN 5
+
+/* The "thumb button" of my Intellimouse. */
+#define MOUSE_SIDE_LEFT 6
+#define MOUSE_SIDE_RIGHT 7
+
+/* EPG settings. */
+
+/* How many chars (max) of the program name to display. */
+#define MAX_PROGRAM_NAME_LENGTH 32
+
#define bcdtoint(i) ((((i & 0xf0) >> 4) * 10) + (i & 0x0f))
typedef struct {
@@ -787,6 +803,7 @@ static int tuner_set_diseqc(tuner_t *this, channel_t *c)
return 1;
}
+
/* Tune to the requested freq. etc, wait for frontend to lock for a few seconds.
* if frontend can't lock, retire. */
static int tuner_tune_it (tuner_t *this, struct dvb_frontend_parameters
@@ -968,10 +985,12 @@ static void dvb_parse_si(dvb_input_plugin_t *this) {
bufptr = tmpbuffer;
pfd.fd=tuner->fd_pidfilter[INTERNAL_FILTER];
- pfd.events = POLLIN;
+ pfd.events = POLLPRI;
xprintf(this->stream->xine,XINE_VERBOSITY_DEBUG,"input_dvb: Setting up Internal PAT filter\n");
+ xine_usec_sleep(500000);
+
/* first - the PAT. retrieve the entire section...*/
dvb_set_sectfilter(this, INTERNAL_FILTER, 0, DMX_PES_OTHER, 0, 0xff);
@@ -1076,7 +1095,8 @@ static void do_eit(dvb_input_plugin_t *this)
char *buffer;
int loops;
int current_channel;
- foo=xine_xmalloc(8192);
+
+ foo = xine_xmalloc(8192);
fd.fd = this->tuner->fd_pidfilter[EITFILTER];
fd.events = POLLPRI;
@@ -1103,6 +1123,7 @@ static void do_eit(dvb_input_plugin_t *this)
for(loops=0;loops<=this->num_streams_in_this_ts*2;loops++){
eit=foo;
+
if (poll(&fd,1,2000)<1) {
xprintf(this->stream->xine,XINE_VERBOSITY_LOG,"(TImeout in EPG loop!! Quitting\n");
return;
@@ -1121,6 +1142,7 @@ static void do_eit(dvb_input_plugin_t *this)
current_next=getbits(foo,47,1);
if(section_len>15){
+
/* do we have information about the current program, or the next? */
if(getbits(foo,192,3) > 2){
@@ -1144,7 +1166,7 @@ static void do_eit(dvb_input_plugin_t *this)
no point in cluttering up the OSD... */
if(bcdtoint(eit[21])+bcdtoint(eit[22])+bcdtoint(eit[23])>0){
strftime(this->channels[current_channel].eit[running_status].starttime,21,"%a %l:%M%p",dvb_mjdtime(eit+16));
- snprintf(this->channels[current_channel].eit[running_status].duration,21,"%ihr%imin",(char)bcdtoint(eit[21] & 0xff),(char)bcdtoint(eit[22] & 0xff));
+ snprintf(this->channels[current_channel].eit[running_status].duration,21,"%i:%02i",(char)bcdtoint(eit[21] & 0xff),(char)bcdtoint(eit[22] & 0xff));
}
descriptor_id=eit[26];
eit+=27;
@@ -1159,14 +1181,27 @@ static void do_eit(dvb_input_plugin_t *this)
case 0x4D: { /* simple program info descriptor */
int name_len;
int desc_len;
- desc_len=getbits(eit,0,8);
- /* printf("LANG Code : %C%C%C\n",eit[1],eit[2],eit[3]); */
+ desc_len = getbits(eit, 0, 8);
+
+ /* Let's get the EPG data only in the wanted language. */
+ xine_cfg_entry_t language;
+ xine_config_lookup_entry(this->stream->xine, "input.dvd_language", &language);
+
+ if (language.str_value && *language.str_value &&
+ strncmp(language.str_value, &eit[1], 2)) {
+ /*printf("### Skipping language: %C%C%C\n",eit[1],eit[2],eit[3]); */
+ break;
+ }
+
/* program name */
- name_len=(unsigned char)eit[4];
- memcpy(this->channels[current_channel].eit[running_status].progname,eit+5,name_len);
+ name_len = (unsigned char)eit[4];
+ memcpy(this->channels[current_channel].eit[running_status].progname,
+ eit + 5, name_len);
+
/* detailed program information (max 256 chars)*/
- text_len=(unsigned char)eit[5+name_len];
- memcpy(this->channels[current_channel].eit[running_status].description,eit+6+name_len,text_len);
+ text_len = (unsigned char)eit[5+name_len];
+ memcpy(this->channels[current_channel].eit[running_status].description,
+ eit + 6 + name_len, text_len);
}
break;
case 0x4E: {
@@ -1207,8 +1242,13 @@ static void do_eit(dvb_input_plugin_t *this)
break;
case 0x54: { /* Content Descriptor, riveting stuff */
int content_bits=getbits(eit,8,4);
- char *content[]={"UNKNOWN","MOVIE","NEWS","ENTERTAINMENT","SPORT","CHILDRENS","MUSIC","ARTS/CULTURE","CURRENT AFFAIRS","EDUCATIONAL","INFOTAINMENT","SPECIAL","COMEDY","DRAMA","DOCUMENTARY","UNK"};
- snprintf(this->channels[current_channel].eit[running_status].content,40,content[content_bits]);
+ char *content[] = {
+ "UNKNOWN","MOVIE","NEWS","ENTERTAINMENT","SPORT",
+ "CHILDRENS","MUSIC","ARTS/CULTURE","CURRENT AFFAIRS",
+ "EDUCATIONAL","INFOTAINMENT","SPECIAL","COMEDY","DRAMA",
+ "DOCUMENTARY","UNK"};
+ snprintf(this->channels[current_channel].eit[running_status].content, 40,
+ content[content_bits]);
}
break;
case 0x55: { /* Parental Rating descriptor describes minimum recommened age -3 */
@@ -1216,7 +1256,13 @@ static void do_eit(dvb_input_plugin_t *this)
printf("descriptor Len: %i\n",getbits(eit,0,8));
printf("Country Code: %C%C%C\n",eit[1],eit[2],eit[3]);
*/
- this->channels[current_channel].eit[running_status].rating=eit[4]+3;
+ /* A rating value of 0 means that there is no rating defined. Ratings
+ greater than 0xF are "defined by broadcaster", which is not supported
+ for now. */
+ if (eit[4] > 0 && eit[4] <= 0xF)
+ this->channels[current_channel].eit[running_status].rating = eit[4] + 3;
+ else
+ this->channels[current_channel].eit[running_status].rating = 0;
}
break;
case 0x57: /* telephone descriptor not used */
@@ -1279,22 +1325,31 @@ static void show_eit(dvb_input_plugin_t *this) {
if(this->channels[this->channel].eit[0].progname!=NULL)
{
this->stream->osd_renderer->set_font(this->proginfo_osd, "sans", 32);
- /* we trim the program name down to 23 chars so it'll fit although with kerning you just don't know */
- snprintf(line,28,"%s",this->channels[this->channel].eit[0].progname);
+ /* we trim the program name down to 23 chars so it'll fit although with kerning you
+ just don't know */
+ snprintf(line, MAX_PROGRAM_NAME_LENGTH, "%s",
+ this->channels[this->channel].eit[0].progname);
this->stream->osd_renderer->render_text (this->proginfo_osd, 100, 46, line,OSD_TEXT4);
this->stream->osd_renderer->set_font(this->proginfo_osd, "sans", 24);
/*start time and duration */
y=0;
if(strlen(this->channels[this->channel].eit[0].starttime)>3){
- snprintf(line,100,"%s(%s)",this->channels[this->channel].eit[0].starttime, this->channels[this->channel].eit[0].duration);
+ snprintf(line,100,"%s (%s)",this->channels[this->channel].eit[0].starttime, this->channels[this->channel].eit[0].duration);
if(strlen(this->channels[this->channel].eit[0].content)>3)
y=15; /* offset vertically */
this->stream->osd_renderer->render_text (this->proginfo_osd, 670, 50+y, line,OSD_TEXT3);
}
/*Content Type and Rating if any*/
if(strlen(this->channels[this->channel].eit[0].content)>3){
- snprintf(line,100,"%s(%i+)",this->channels[this->channel].eit[0].content, this->channels[this->channel].eit[0].rating);
+
+ snprintf(line, 94, "%s", this->channels[this->channel].eit[0].content);
+
+ const int prog_rating = this->channels[this->channel].eit[0].rating;
+ if (prog_rating > 0) {
+ snprintf(line + strlen(line), 7, " (%i+)", prog_rating);
+ }
+
this->stream->osd_renderer->render_text (this->proginfo_osd, 670, 20+y, line,OSD_TEXT3);
}
/* some quick'n'dirty formatting to keep words whole */
@@ -1314,8 +1369,9 @@ static void show_eit(dvb_input_plugin_t *this) {
}
} else {
this->stream->osd_renderer->set_font(this->proginfo_osd, "sans", 32);
- /* we trim the program name down to 23 chars so it'll fit although with kerning you just don't know */
- snprintf(line,28,"%s","No Information Available");
+ /* we trim the program name down so it'll fit although with kerning you just
+ don't know */
+ snprintf(line, MAX_PROGRAM_NAME_LENGTH, "%s", "No Information Available");
this->stream->osd_renderer->render_text (this->proginfo_osd, 100, 46, line,OSD_TEXT4);
this->stream->osd_renderer->set_font(this->proginfo_osd, "sans", 24);
}
@@ -1323,21 +1379,30 @@ static void show_eit(dvb_input_plugin_t *this) {
if(this->channels[this->channel].eit[1].progname!=NULL)
{
/* and now the next program */
- snprintf(line,28,"%s",this->channels[this->channel].eit[1].progname);
+ snprintf(line, MAX_PROGRAM_NAME_LENGTH, "%s",
+ this->channels[this->channel].eit[1].progname);
this->stream->osd_renderer->set_font(this->proginfo_osd, "sans", 32);
this->stream->osd_renderer->render_text (this->proginfo_osd, 100, 296, line,OSD_TEXT4);
this->stream->osd_renderer->set_font(this->proginfo_osd, "sans", 24);
y=0;
if(strlen(this->channels[this->channel].eit[1].starttime)>3){
- snprintf(line,100,"%s(%s)",this->channels[this->channel].eit[1].starttime, this->channels[this->channel].eit[1].duration);
+ snprintf(line,100,"%s (%s)",this->channels[this->channel].eit[1].starttime, this->channels[this->channel].eit[1].duration);
if(strlen(this->channels[this->channel].eit[1].content)>3)
y=15; /* offset vertically */
this->stream->osd_renderer->render_text (this->proginfo_osd, 670, 300+y, line,OSD_TEXT3);
}
/*Content Type and Rating if any*/
if(strlen(this->channels[this->channel].eit[1].content)>3){
- snprintf(line,100,"%s(%i+)",this->channels[this->channel].eit[1].content, this->channels[this->channel].eit[1].rating);
+
+ snprintf(line, 94, "%s", this->channels[this->channel].eit[1].content);
+
+ const int prog_rating = this->channels[this->channel].eit[1].rating;
+ if (prog_rating > 0) {
+ snprintf(line + strlen(line), 7, " (%i+)", prog_rating);
+ }
+
+
this->stream->osd_renderer->render_text (this->proginfo_osd, 670, 270+y, line,OSD_TEXT3);
}
/* some quick'n'dirty formatting to keep words whole */
@@ -1395,9 +1460,6 @@ static int tuner_set_channel (dvb_input_plugin_t *this,
if (!tuner_tune_it (tuner, &c->front_param))
return 0;
-
- /* now read the pat,find all accociated PIDs and add them to the stream */
- dvb_parse_si(this);
return 1; /* fixme: error handling */
}
@@ -1489,6 +1551,9 @@ static void switch_channel (dvb_input_plugin_t *this) {
pthread_mutex_unlock (&this->mutex);
+ /* now read the pat,find all accociated PIDs and add them to the stream */
+ dvb_parse_si(this);
+
this->stream->osd_renderer->hide(this->channel_osd,0);
/* show eit for this channel if necessary */
if(this->displaying==1){
@@ -1561,6 +1626,7 @@ static void do_record (dvb_input_plugin_t *this) {
static void dvb_event_handler (dvb_input_plugin_t *this) {
xine_event_t *event;
+ static int channel_menu_visible = 0;
while ((event = xine_event_get (this->event_queue))) {
@@ -1573,21 +1639,75 @@ static void dvb_event_handler (dvb_input_plugin_t *this) {
switch (event->type) {
+ case XINE_EVENT_INPUT_MOUSE_BUTTON: {
+ xine_input_data_t *input = (xine_input_data_t*)event->data;
+ switch (input->button) {
+
+ case MOUSE_BUTTON_LEFT:
+ if (channel_menu_visible) {
+ channel_menu_visible = 0;
+ switch_channel (this);
+ } else {
+ show_eit(this);
+ }
+ break;
+
+ case MOUSE_WHEEL_UP:
+ if (this->channel>0)
+ this->channel--;
+ channel_menu_visible = 1;
+ osd_show_channel (this);
+
+ break;
+
+ case MOUSE_WHEEL_DOWN:
+ if (this->channel < (this->num_channels-1))
+ this->channel++;
+ channel_menu_visible = 1;
+ osd_show_channel (this);
+ break;
+
+ case MOUSE_SIDE_LEFT:
+ if (this->channel > 0) {
+ this->channel--;
+ channel_menu_visible = 0;
+ switch_channel (this);
+ }
+ break;
+
+ case MOUSE_SIDE_RIGHT:
+ if (this->channel < (this->num_channels-1)) {
+ this->channel++;
+ channel_menu_visible = 0;
+ switch_channel (this);
+ }
+ break;
+
+ default:
+ printf("Unknown mouse button number: %d.\n", input->button);
+ /* Unknown mouse event. */
+ }
+ break;
+ }
+
case XINE_EVENT_INPUT_DOWN:
if (this->channel < (this->num_channels-1))
this->channel++;
+ channel_menu_visible = 1;
osd_show_channel (this);
break;
case XINE_EVENT_INPUT_UP:
if (this->channel>0)
this->channel--;
+ channel_menu_visible = 1;
osd_show_channel (this);
break;
case XINE_EVENT_INPUT_NEXT:
if (this->channel < (this->num_channels-1)) {
this->channel++;
+ channel_menu_visible = 0;
switch_channel (this);
}
break;
@@ -1595,16 +1715,19 @@ static void dvb_event_handler (dvb_input_plugin_t *this) {
case XINE_EVENT_INPUT_PREVIOUS:
if (this->channel>0) {
this->channel--;
+ channel_menu_visible = 0;
switch_channel (this);
}
break;
case XINE_EVENT_INPUT_SELECT:
+ channel_menu_visible = 0;
switch_channel (this);
break;
case XINE_EVENT_INPUT_MENU1:
this->stream->osd_renderer->hide (this->osd, 0);
+ channel_menu_visible = 0;
break;
case XINE_EVENT_INPUT_MENU2:
@@ -1635,10 +1758,10 @@ static void dvb_event_handler (dvb_input_plugin_t *this) {
break;
case XINE_EVENT_INPUT_MENU7:
+ channel_menu_visible = 0;
show_eit(this);
break;
-
#if 0
default:
printf ("input_dvb: got an event, type 0x%08x\n", event->type);
@@ -2089,8 +2212,9 @@ static int dvb_plugin_open(input_plugin_t * this_gen)
_("input_dvb: cannot open dvr device '%s'\n"), this->tuner->dvr_device);
return 0;
}
- if(ioctl(this->fd,DMX_SET_BUFFER_SIZE,188*1024)<0)
- xprintf(this->class->xine,XINE_VERBOSITY_DEBUG,"input_dvb: couldn't increase buffer size for DVR: %s \n",strerror(errno));
+
+ /* now read the pat,find all accociated PIDs and add them to the stream */
+ dvb_parse_si(this);
this->curpos = 0;
this->osd = NULL;
@@ -2376,39 +2500,39 @@ static void *init_class (xine_t *xine, void *data) {
xprintf(this->xine,XINE_VERBOSITY_DEBUG,"init class succeeded\n");
- /* dislay channel name in top left of display */
- config->register_bool(config, "input.dvbdisplaychan",
- 0,
- _("display DVB channel name"),
- _("This will display the current "
- "channel name in xine's on-screen-display. "
- "Menu button 7 will disable this temporarily."),
- 0, NULL, NULL);
-
- /* Enable remembering of last watched channel */
- config->register_bool(config, "input.dvb_last_channel_enable",
- 1,
- _("Remember last DVB channel watched"),
- _("On autoplay, xine will remember and "
- "switch to this channel. "),
- 0, NULL, NULL);
-
-
- /* Enable remembering of last watched channel never show this entry*/
- config->register_num(config, "input.dvb_last_channel_watched",
- -1,
- _("Remember last DVB channel watched"),
- _("If enabled, xine will remember and "
- "switch to this channel. "),
- 11, NULL, NULL);
-
- config->register_num(config, "input.dvb_adapternum",
- 0,
- _("Number of dvb card to use."),
- _("Leave this at zero unless you "
- "really have more than 1 card "
- "in your system."),
- 0, NULL, (void *) this);
+ /* dislay channel name in top left of display */
+ config->register_bool(config, "input.dvbdisplaychan",
+ 0,
+ _("display DVB channel name"),
+ _("This will display the current "
+ "channel name in xine's on-screen-display. "
+ "Menu button 7 will disable this temporarily."),
+ 0, NULL, NULL);
+
+ /* Enable remembering of last watched channel */
+ config->register_bool(config, "input.dvb_last_channel_enable",
+ 1,
+ _("Remember last DVB channel watched"),
+ _("On autoplay, xine will remember and "
+ "switch to this channel. "),
+ 0, NULL, NULL);
+
+ /* Enable remembering of last watched channel never show this entry*/
+ config->register_num(config, "input.dvb_last_channel_watched",
+ -1,
+ _("Remember last DVB channel watched"),
+ _("If enabled, xine will remember and "
+ "switch to this channel. "),
+ 11, NULL, NULL);
+
+
+ config->register_num(config, "input.dvb_adapternum",
+ 0,
+ _("Number of dvb card to use."),
+ _("Leave this at zero unless you "
+ "really have more than 1 card "
+ "in your system."),
+ 0, NULL, (void *) this);
return this;