Example #1
0
void osd_alert(struct osd_t* osd, char* text)
{
  uint32_t text_length;
  uint32_t width,height;
  uint32_t y_offset;
  uint32_t x_offset;
  uint32_t text_size = 40;

  pthread_mutex_lock(&osd->osd_mutex);

  /* TODO: Only clear alert area */
  graphics_resource_fill(osd->img, 0, 0, osd->display_width, osd->display_height, GRAPHICS_RGBA32(0,0,0,0));

  if (text) {
    fprintf(stderr,"[OSD ALERT]: %s\n",text);
    text_length = strlen(text);
    graphics_resource_text_dimensions_ext(osd->img, text, text_length, &width, &height, text_size);

    x_offset = ((1920 - width) / 2);
    y_offset = (1080 - height) / 2;

    osd_draw_window(osd,x_offset,y_offset,width+100,height+50);

    graphics_resource_render_text_ext(osd->img, x_offset+50, y_offset+25,
                                          width,
                                          height,
                                          GRAPHICS_RGBA32(0xff,0xff,0xff,0xff), /* fg */
                                          GRAPHICS_RGBA32(0,0,0,0x80), /* bg */
                                          text, text_length, text_size);
  }

  graphics_update_displayed_resource(osd->img, 0, 0, 0, 0);

  pthread_mutex_unlock(&osd->osd_mutex);
}
Example #2
0
/*
 * Render paragraph. TODO: fix line break in long text without spaces.
 */
int32_t osd_paragraph(struct osd_t* osd, char *text, uint32_t text_size, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
{
  uint32_t width;
  char* iso_text = NULL;
  char* str;
  char* tmp;
  char* space;
  int text_y = y;
  int done = 0;

  if ((!text) || (strlen(text) == 0)) {
    return 0;
  }
  
  iso_text = malloc(strlen(text) + 1);
  utf8decode(text, iso_text);  
  str = iso_text;
  
  do {
    width = osd_fontWidth(osd, str, strlen(str));
    
    if (width <= w) {
      /* We can display the whole line */      
      graphics_resource_render_text_ext(osd->img, x, text_y,
                                   GRAPHICS_RESOURCE_WIDTH,
                                   GRAPHICS_RESOURCE_HEIGHT,
                                   GRAPHICS_RGBA32(0xff,0xff,0xff,0xff), /* fg */
                                   GRAPHICS_RGBA32(0,0,0,0xc0), /* bg */
                                   str, strlen(str), 40);                                 
      done = 1;                             
    } else {
      tmp = malloc(strlen(str) + 1);
      strcpy(tmp, str);
      while (width > w) {
        space = strrchr(tmp, ' ');  
        tmp[space-tmp] = '\0';
        width = osd_fontWidth(osd, tmp, space - tmp);
      }
      
      graphics_resource_render_text_ext(osd->img, x, text_y,
                                       GRAPHICS_RESOURCE_WIDTH,
                                       GRAPHICS_RESOURCE_HEIGHT,
                                       GRAPHICS_RGBA32(0xff,0xff,0xff,0xff), /* fg */
                                       GRAPHICS_RGBA32(0,0,0,0xc0), /* bg */
                                       tmp, strlen(tmp), 40);                                       
      text_y += 50;  
      if (text_y > (y + h)) {
        done = 1;
      }  
      str += strlen(tmp) + 1;
      free(tmp);
    }
  } while(!done);
  
  free(iso_text);  
  return 0;
}
Example #3
0
void osd_draw_window(struct osd_t* osd, int x, int y, int width, int height)
{
   graphics_resource_fill(osd->img, x, y, width, height, GRAPHICS_RGBA32(0,0,0,0xC0));

   graphics_resource_fill(osd->img, x, y, width, 2, GRAPHICS_RGBA32(0xff,0xff,0xff,0xa0));
   graphics_resource_fill(osd->img, x, y+height-2, width, 2, GRAPHICS_RGBA32(0xff,0xff,0xff,0xa0));
   graphics_resource_fill(osd->img, x, y, 2, height, GRAPHICS_RGBA32(0xff,0xff,0xff,0xa0));
   graphics_resource_fill(osd->img, x+width-2, y, 2, height, GRAPHICS_RGBA32(0xff,0xff,0xff,0xa0));
}
Example #4
0
void doPaint(struct OSD_T *osd, void *opaque)
{
	logInfo( LOG_CLIENT,"1. Here we are.\n");

	osdClear(osd);
	osdDrawRect(osd, 10, 10, 110, 110, GRAPHICS_RGBA32(255,255,255,125), GRAPHICS_RGBA32(0,255,0,125), 1);
	osdDrawRect(osd, 20, 20, 80, 80, GRAPHICS_RGBA32(255,255,255,125), GRAPHICS_RGBA32(0,0,255,255), 1);

	logInfo( LOG_CLIENT,"2. Here we are.\n");
}
Example #5
0
void doPaintTitle(struct OSD_T *osd, void *opaque)
{
	logInfo( LOG_CLIENT,"1. Here we are.\n");

	osdClear(osd);
	osdDrawRect(osd, 10, 10, 1000, 110, GRAPHICS_RGBA32(255,255,255,255), GRAPHICS_RGBA32(0,255,0,125), 1);

	osdDrawText(osd, 30, 30, programTitle, 50, GRAPHICS_RGBA32(255,255,255,255), GRAPHICS_RGBA32(255,0,0,255), 1);

	logInfo( LOG_CLIENT,"2. Here we are.\n");
}
Example #6
0
void osd_init(struct osd_t* osd)
{
  uint32_t display_width, display_height;
  char str[2] = { 0, 0 };
  uint32_t width, height;
  int n;
  int s;

  s = gx_graphics_init(tiresias_pcfont, sizeof(tiresias_pcfont));
  assert(s == 0);

  s = graphics_get_display_size(0, &display_width, &display_height);
  osd->display_width = display_width;
  osd->display_height = display_height;

  printf("osd_init: %d %d\n", display_width, display_height);
  
  assert(s == 0);
  //fprintf(stderr,"Display width=%d, height=%d\n",display_width,display_height);

  /* The main OSD image */
  s = gx_create_window(SCREEN, display_width, display_height, GRAPHICS_RESOURCE_RGBA32, &osd->img);
  assert(s == 0);
  graphics_resource_fill(osd->img, 0, 0, display_width, display_height, GRAPHICS_RGBA32(0,0,0,0));

  graphics_display_resource(osd->img, 0, OSD_LAYER, 0, 0, GRAPHICS_RESOURCE_WIDTH, GRAPHICS_RESOURCE_HEIGHT, VC_DISPMAN_ROT0, 1);

  /* A full-screen black image to either remove any left-over console text (BG_LAYER) or to hide the video (FG_LAYER) */
  s = gx_create_window(SCREEN, display_width, display_height, GRAPHICS_RESOURCE_RGBA32, &osd->img_blank);
  assert(s == 0);
  graphics_resource_fill(osd->img_blank, 0, 0, display_width, display_height, GRAPHICS_RGBA32(0,0,0,255));

  graphics_display_resource(osd->img_blank, 0, BG_LAYER, 0, 0, GRAPHICS_RESOURCE_WIDTH, GRAPHICS_RESOURCE_HEIGHT, VC_DISPMAN_ROT0, 1);

  osd->video_blanked = 0;
  osd->osd_cleartime = 0.0;
  osd->last_now = time(NULL);
  
  pthread_mutex_init(&osd->osd_mutex,NULL);
   
  // cache font widths since graphics_resource_text_dimensions_ext is kind of slow
  for (n = 32; n < 256; n++) {
    str[0] = n;
    graphics_resource_text_dimensions_ext(osd->img, str, 1, &width, &height, 40); 
    fontWidth[n] = (uint8_t)width;
  }
    
  (void)s; // remove compiler warning
}
Example #7
0
int main(void)
{
   GRAPHICS_RESOURCE_HANDLE img;
   uint32_t width, height;
   int LAYER=1;
   bcm_host_init();
   int s;

   s = gx_graphics_init(".");
   assert(s == 0);

   s = graphics_get_display_size(0, &width, &height);
   assert(s == 0);

   s = gx_create_window(0, width, height, GRAPHICS_RESOURCE_RGBA32, &img);
   assert(s == 0);

   // transparent before display to avoid screen flash
   graphics_resource_fill(img, 0, 0, width, height, GRAPHICS_RGBA32(0,0,0,0x00));

   graphics_display_resource(img, 0, LAYER, 0, 0, GRAPHICS_RESOURCE_WIDTH, GRAPHICS_RESOURCE_HEIGHT, VC_DISPMAN_ROT0, 1);

   uint32_t text_size = 10;
   while (1) {
      const char *text = "The quick brown fox jumps over the lazy dog";
      uint32_t y_offset = height-60+text_size/2;
      graphics_resource_fill(img, 0, 0, width, height, GRAPHICS_RGBA32(0,0,0,0x00));
      // blue, at the top (y=40)
      graphics_resource_fill(img, 0, 40, width, 1, GRAPHICS_RGBA32(0,0,0xff,0xff));

      // green, at the bottom (y=height-40)
      graphics_resource_fill(img, 0, height-40, width, 1, GRAPHICS_RGBA32(0,0xff,0,0xff));

      // draw the subtitle text
      render_subtitle(img, text, 0, text_size,  y_offset);
      graphics_update_displayed_resource(img, 0, 0, 0, 0);
      text_size += 1;
      if (text_size > 50)
         text_size = 10;
   }

   graphics_display_resource(img, 0, LAYER, 0, 0, GRAPHICS_RESOURCE_WIDTH, GRAPHICS_RESOURCE_HEIGHT, VC_DISPMAN_ROT0, 0);
   graphics_delete_resource(img);

   return 0;
}
Example #8
0
void osd_clear_newchannel(struct osd_t* osd)
{
  /* TODO: Only clear channel area */

  pthread_mutex_lock(&osd->osd_mutex);
  graphics_resource_fill(osd->img, 0, 0, osd->display_width, osd->display_height, GRAPHICS_RGBA32(0,0,0,0));
  graphics_update_displayed_resource(osd->img, 0, 0, 0, 0);
  pthread_mutex_unlock(&osd->osd_mutex);

  fprintf(stderr,"Clearing OSD...\n");
}
Example #9
0
int32_t render_subtitle(GRAPHICS_RESOURCE_HANDLE img, const char *text, const int skip, const uint32_t text_size, const uint32_t y_offset)
{
   uint32_t text_length = strlen(text)-skip;
   uint32_t width=0, height=0;
   const char *split = text;
   int32_t s=0;
   int len = 0; // length of pre-subtitle
   uint32_t img_w, img_h;

   graphics_get_resource_size(img, &img_w, &img_h);

   if (text_length==0)
      return 0;
   while (split[0]) {
      s = graphics_resource_text_dimensions_ext(img, split, text_length-(split-text), &width, &height, text_size);
      if (s != 0) return s;
      if (width > img_w) {
         const char *space = strnchr(split, text_length-(split-text), ' ');
         if (!space) {
            len = split+1-text;
            split = split+1;
         } else {
            len = space-text;
            split = space+1;
         }
      } else {
         break;
      }
   }
   // split now points to last line of text. split-text = length of initial text. text_length-(split-text) is length of last line
   if (width) {
      s = graphics_resource_render_text_ext(img, (img_w - width)>>1, y_offset-height,
                                     GRAPHICS_RESOURCE_WIDTH,
                                     GRAPHICS_RESOURCE_HEIGHT,
                                     GRAPHICS_RGBA32(0xff,0xff,0xff,0xff), /* fg */
                                     GRAPHICS_RGBA32(0,0,0,0x80), /* bg */
                                     split, text_length-(split-text), text_size);
      if (s!=0) return s;
   }
   return render_subtitle(img, text, skip+text_length-len, text_size, y_offset - height);
}
Example #10
0
void osd_clear(struct osd_t* osd)
{
  pthread_mutex_lock(&osd->osd_mutex);
  graphics_resource_fill(osd->img, 0, 0, osd->display_width, osd->display_height, GRAPHICS_RGBA32(0,0,0,0));
  graphics_update_displayed_resource(osd->img, 0, 0, 0, 0);
  pthread_mutex_unlock(&osd->osd_mutex);

  fprintf(stderr,"Clearing OSD...\n");

  osd->osd_state = OSD_NONE;
  osd->osd_cleartime = 0;
}
Example #11
0
static void osd_show_time(struct osd_t* osd)
{
  struct tm now_tm;
  time_t now;
  char str[32];
  int width = 218;
  int height = 80;

  osd_draw_window(osd,1670,18,width,height);

  now = time(NULL);
  localtime_r(&now,&now_tm);

  snprintf(str,sizeof(str),"%02d:%02d.%02d",now_tm.tm_hour,now_tm.tm_min,now_tm.tm_sec);

  graphics_resource_render_text_ext(osd->img, 1700, OSD_YMARGIN+25,
                                     width,
                                     height,
                                     GRAPHICS_RGBA32(0xff,0xff,0xff,0xff), /* fg */
                                     GRAPHICS_RGBA32(0,0,0,0x80), /* bg */
                                     str, strlen(str), 40);
}
Example #12
0
static void osd_show_channelname(struct osd_t* osd, const char *text)
{
   uint32_t text_length = strlen(text);
   uint32_t width,height;
   uint32_t y_offset = OSD_YMARGIN;
   uint32_t x_offset = OSD_XMARGIN;
   uint32_t text_size = 40;

   //s = graphics_resource_text_dimensions_ext(osd->img, text, text_length, &width, &height, text_size);

   height = 80;
   width = 600;

   osd_draw_window(osd,x_offset,y_offset,width,height);

   graphics_resource_render_text_ext(osd->img, x_offset+50, y_offset+25,
                                     width,
                                     height,
                                     GRAPHICS_RGBA32(0xff,0xff,0xff,0xff), /* fg */
                                     GRAPHICS_RGBA32(0,0,0,0x80), /* bg */
                                     text, text_length, text_size);

}
Example #13
0
static void osd_show_eventinfo(struct osd_t* osd, struct event_t* event, struct event_t* nextEvent)
{
  char str[64];
  struct tm start_time;
  struct tm stop_time;
  int duration;
  int width = 1920-2*OSD_XMARGIN;
  int height = 380-OSD_YMARGIN;

  osd_draw_window(osd,OSD_XMARGIN,700,width,height);

  if (event==NULL)
    return;

  /* Start/stop time - current event */
  localtime_r((time_t*)&event->start,&start_time);
  localtime_r((time_t*)&event->stop,&stop_time);
  duration = event->stop - event->start;

  snprintf(str,sizeof(str),"%02d:%02d - %02d:%02d",start_time.tm_hour,start_time.tm_min,stop_time.tm_hour,stop_time.tm_min);
  graphics_resource_render_text_ext(osd->img, OSD_XMARGIN+50, 720,
                                     width,
                                     height,
                                     GRAPHICS_RGBA32(0xff,0xff,0xff,0xff), /* fg */
                                     GRAPHICS_RGBA32(0,0,0,0x80), /* bg */
                                     str, strlen(str), 40);

  /* Title - current event */
  if (event->title) {
    char* iso_text = malloc(strlen(event->title)+1);
    utf8decode(event->title,iso_text);
    graphics_resource_render_text_ext(osd->img, OSD_XMARGIN+350, 720,
                                       width,
                                       height,
                                       GRAPHICS_RGBA32(0xff,0xff,0xff,0xff), /* fg */
                                       GRAPHICS_RGBA32(0,0,0,0x80), /* bg */
                                       iso_text, strlen(iso_text), 40);
    free(iso_text);
  }

  snprintf(str,sizeof(str),"%dh %02dm",duration/3600,(duration%3600)/60);
  graphics_resource_render_text_ext(osd->img, OSD_XMARGIN+50, 800,
                                     width,
                                     height,
                                     GRAPHICS_RGBA32(0xff,0xff,0xff,0xff), /* fg */
                                     GRAPHICS_RGBA32(0,0,0,0x80), /* bg */
                                     str, strlen(str), 30);

  if ((event->episodeNumber) || (event->seasonNumber)) {
    if (!event->episodeNumber) {
      snprintf(str,sizeof(str),"Season %d",event->seasonNumber);
    } else if (!event->seasonNumber) {
      snprintf(str,sizeof(str),"Episode %d",event->episodeNumber);
    } else {
      snprintf(str,sizeof(str),"Season %d, Ep. %d",event->seasonNumber,event->episodeNumber);
    }
    graphics_resource_render_text_ext(osd->img, OSD_XMARGIN+50, 838,
                                     width,
                                     height,
                                     GRAPHICS_RGBA32(0xff,0xff,0xff,0xff), /* fg */
                                     GRAPHICS_RGBA32(0,0,0,0x80), /* bg */
                                     str, strlen(str), 30);
  }

  if (event->description) {
    char* iso_text = malloc(strlen(event->description)+1);
    utf8decode(event->description,iso_text);
    render_paragraph(osd->img,iso_text,30,OSD_XMARGIN+350,800);
    free(iso_text);
  }


  if (nextEvent) {
    osd_draw_window(osd,OSD_XMARGIN,1002,width,78-OSD_YMARGIN);
    /* Start/stop time - next event */
    localtime_r((time_t*)&nextEvent->start,&start_time);
    localtime_r((time_t*)&nextEvent->stop,&stop_time);

    snprintf(str,sizeof(str),"%02d:%02d - %02d:%02d",start_time.tm_hour,start_time.tm_min,stop_time.tm_hour,stop_time.tm_min);
    graphics_resource_render_text_ext(osd->img, OSD_XMARGIN+50, 1020,
                                       width,
                                       height,
                                       GRAPHICS_RGBA32(0xff,0xff,0xff,0xff), /* fg */
                                       GRAPHICS_RGBA32(0,0,0,0x80), /* bg */
                                       str, strlen(str), 40);


    if (nextEvent->title) {
      char* iso_text = malloc(strlen(nextEvent->title)+1);
      utf8decode(nextEvent->title,iso_text);
      graphics_resource_render_text_ext(osd->img, OSD_XMARGIN+350, 1020,
                                         width,
                                         height,
                                         GRAPHICS_RGBA32(0xff,0xff,0xff,0xff), /* fg */
                                         GRAPHICS_RGBA32(0,0,0,0x80), /* bg */
                                         iso_text, strlen(iso_text), 40);
      free(iso_text);
    }
  }


  //fprintf(stderr,"Title:       %s\n",event->title);
  //fprintf(stderr,"Start:       %04d-%02d-%02d %02d:%02d:%02d\n",start_time.tm_year+1900,start_time.tm_mon+1,start_time.tm_mday,start_time.tm_hour,start_time.tm_min,start_time.tm_sec);
  //fprintf(stderr,"Stop:        %04d-%02d-%02d %02d:%02d:%02d\n",stop_time.tm_year+1900,stop_time.tm_mon+1,stop_time.tm_mday,stop_time.tm_hour,stop_time.tm_min,stop_time.tm_sec);
  //fprintf(stderr,"Duration:    %02d:%02d:%02d\n",
  //fprintf(stderr,"Description: %s\n",event->description);
}
Example #14
0
int32_t render_paragraph(GRAPHICS_RESOURCE_HANDLE img, const char *text, const uint32_t text_size, const uint32_t x_offset, const uint32_t y_offset)
{
   uint32_t text_length;
   uint32_t line_length;
   uint32_t width=0, height=0;
   const char *split = text;
   int32_t s=0;
   uint32_t img_w = 1400;;

   if ((!text) || ((text_length=strlen(text))==0))
      return 0;

   //fprintf(stderr,"render_paragraph(\"%s\",%d)\n",text,text_length);

   s = graphics_resource_text_dimensions_ext(img, text, text_length, &width, &height, text_size);
   if (s != 0) return s;

   if (width <= img_w) {
     /* We can display the whole line */
     line_length = text_length;
   } else {
     //fprintf(stderr,"width=%d, img_w=%d, looking for next space\n",width,img_w);

     const char* space = index(split,' ');

     if (space) {
       s = graphics_resource_text_dimensions_ext(img, text, space-text, &width, &height, text_size);
       if (s != 0) return s;
     }

     if ((space == NULL) || (width > img_w)) {
       /* No spaces, within img_w. Just go through character by character */
       line_length = 0;
       do {
         line_length++;
         s = graphics_resource_text_dimensions_ext(img, text, text_length, &width, &height, text_size);
         if (s != 0) return s;
       } while (width < img_w);

       line_length--;
     } else {
       /* We have at least one space, so can split line on a space */
       width = 0;
       line_length = space - text;

       while (width < img_w) {
         space = index(space+1,' ');
         s = graphics_resource_text_dimensions_ext(img, text, space - text, &width, &height, text_size);
         if (s != 0) return s;

         if (width < img_w) { line_length = space - text; }
       }
     }
   }

   if (line_length) {
     //int i;
     //fprintf(stderr,"Rendering: ");
     //for (i=0;i<line_length;i++) { fprintf(stderr,"%c",text[i]); }
     //fprintf(stderr,"\n");

     s = graphics_resource_render_text_ext(img, x_offset, y_offset,
                                     GRAPHICS_RESOURCE_WIDTH,
                                     GRAPHICS_RESOURCE_HEIGHT,
                                     GRAPHICS_RGBA32(0xff,0xff,0xff,0xff), /* fg */
                                     GRAPHICS_RGBA32(0,0,0,0x80), /* bg */
                                     text, line_length, text_size);
      if (s!=0) return s;
   }
   if (text[line_length]) {
     return render_paragraph(img, text + line_length+1, text_size, x_offset, y_offset + height);
   } else {
     return 0;
   }
}
Example #15
0
int main(int argc, char *argv[])
{
	int error = 0;
	char response[6000];
	struct LISTITEM_T *tmpDetails;
	fd_set our_fd_set, working_fd_set;
	int maxSocket;
	struct timeval timeout;
	int rc;
	char *hostname = HOST;
	int port = PORT;
	int startChannelNum = 1;
	struct DEMUXER_T *demuxer = NULL;
	uint8_t stdinBuffer;
	uint32_t newChannel = 0;
	uint32_t newChannel2 = 0;
	uint32_t currentChannel = 0;
	int channelChanged = 0;
	int audioPassthrough = 1;
	int showVideo = 1;
	int playAudio = 1;
	char *recordingFilename = NULL;
	char *newFileName = NULL;

	int c;
	opterr = 0;

	signal(SIGINT, catchedCtrlC);
	signal(SIGKILL, catchedKill);

/*
	-h <hostname>
	-p <port>
	-c <channelnumber>
	-l <comma separated list of logattributes to turn on>  "client, mythprotocol, demuxer, omx, client-debug, mythprotocol-debug, demuxer-debug, omx-debug"
	-t <language code> "e.g. dut for dutch"
	-a <0|1> "Set audio on or off. Default 1 (on)"
	-v <0|1> "Set video on or off. Default 1 (on)"
	-e <0|1> "Set audio passthrough on. Decoding is done externally. Default 0 (off)"
	-r <recording filename | list>  list will show details of all recordings while a "recording name" will start the playback of a the specified recording.
			e.g.: "recording filename" == 20024_20121201183000.mpg  <-  file name can be found in recording directory of mythtvbackend. 
*/

	while ((c = getopt(argc, argv, "h:p:c:l:t:e:a:v:r:")) != -1)
		switch (c) {
		case 'h':
			hostname = optarg;
			break;
		case 'p':
			port = atoi(optarg);
			break;
		case 'c':
			startChannelNum = atoi(optarg);
			break;
		case 'l':
			setLogLevelByStr(optarg);
			break;
		case 't':
			demuxerSetLanguage(optarg);
			break;
		case 'e':
			audioPassthrough = atoi(optarg);
			break;
		case 'a':
			playAudio = atoi(optarg);
			break;
		case 'v':
			showVideo = atoi(optarg);
			break;
		case 'r':
			recordingFilename = optarg;
			break;
		}

	changeSTDIN();

	initializeBCM();

#ifdef PI
	tvserviceInit();

//	tvservicePowerOff();
//	sleep(1);
//	tvserviceHDMIPowerOnBest(0, 1080, 720, 50, 0);
//	sleep(1);

/* 	struct OSD_T *osd2 = osdCreate(1, 0, 0, GRAPHICS_RGBA32(255,0,0,0xff), &doPaint);
	if (osd2 == NULL) {
		printf("osdCreate osd2 error.\n");
		exit(1);
	}
*/
 	struct OSD_T *osdTitle = osdCreate(1, 0, 0, GRAPHICS_RGBA32(0,0,0,0x0), &doPaintTitle);
	if (osdTitle == NULL) {
		printf("osdCreate osdTitle error.\n");
		exit(1);
	}

	if (osdSetFont(osdTitle, "/usr/share/fonts/truetype/freefont/FreeSans.ttf") != 0) {
		printf("osdSetFont could not set font.\n");
		exit(1);
	}

//	osdDrawText(osd2, 200, 200, "DIT IS EEN TEST BERICHT", 50);
//	osdShow(osd2, NULL);

/*	struct OSD_T *osd1 = osdCreate(2, 500, 500, 0x80);
	if (osd1 == NULL) {
		printf("osdCreate osd1 error.\n");
		exit(1);
	}
	osdDraw(osd1);
*/
/*	int i;
	osdDrawText(osd, 0, 0, "Hello", 30);
	for(i=0; i<1000; i=i+100) {
		osdShow(osd, i, i);
		sleep(5);
	}*/

	logInfo( LOG_CLIENT,"the end.\n");
	sleep(2);

//	osdDestroy(osd1);
//	osdDestroy(osd2);
//	osdHide(osd2);

//	tvserviceDestroy();
//	bcm_host_deinit();

//	exit(1);
#else
	struct OSD_T *img = osdCreate(1, 0, 0);
//	osdDrawText(img, 0, 0, "Hello", 11);
	osdDestroy(img);
#endif

	masterConnection = createMythConnection(hostname, port, ANN_PLAYBACK);
	if (masterConnection == NULL) {
		error = -1;
		logInfo( LOG_CLIENT,"Could not create master Connection.\n");
		return -1;
	}

#ifdef DEBUG
	logInfo( LOG_CLIENT,"main: We have a valid connection to the master backend.\n");
#endif

	if (error >= 0) {
		error = mythRefreshBackend(masterConnection);
	}

	if ((error >= 0) && (recordingFilename != NULL) && (strcmp(recordingFilename, "list") == 0)) {
		logInfo( LOG_CLIENT,"Going to show a list of recordings.\n");

		mythQueryRecordings(masterConnection, "Descending");
		destroyMythConnection(masterConnection);
		return 0;
	}

	if (error >= 0) {
		monitorConnection = createMythConnection(hostname, port, ANN_MONITOR);
		if (monitorConnection == NULL) {
			error = -1;
		}
	}

	if (error >= 0) {
		if (recordingFilename == NULL) {
			slaveConnection = startLiveTV(masterConnection, startChannelNum);
		}
		else {
			slaveConnection = checkRecorderProgram(masterConnection, recordingFilename);
		}
		if (slaveConnection == NULL) {
			error = -1;
		}
		newChannel2 = startChannelNum;
		currentChannel = startChannelNum;
	}

	FD_ZERO(&our_fd_set);

	FD_SET(monitorConnection->connection->socket, &our_fd_set);
	maxSocket = monitorConnection->connection->socket;

	FD_SET(STDIN, &our_fd_set);
	if (STDIN > maxSocket) {
		maxSocket = STDIN;
	}
	
	int changingChannel = 0;

	if ((error >=0) && (recordingFilename != NULL)) {
		error = playRecorderProgram(slaveConnection);
		if (error >= 0) {
			demuxer = demuxerStart(slaveConnection, showVideo, playAudio, 1, audioPassthrough);
		}
	}
	
	ssize_t bytesRead;

	if (error >= 0) {
		int firstStartRecording = 0;
		int dataAvailable = 0;

		logInfo( LOG_CLIENT,"Going to start main loop.\n");
		while (doStop == 0) {

			dataAvailable = mythDataAvailableOnConnection(monitorConnection->connection);

			memcpy(&working_fd_set, &our_fd_set, sizeof(our_fd_set));

			timeout.tv_sec  = 0;
			if (dataAvailable == 0) {
				timeout.tv_usec = 10000;
			}
			else {
				timeout.tv_usec = 10000;
			}

			rc = select(maxSocket+1, &working_fd_set, NULL, NULL, &timeout);
			if (rc < 0) {
				perror("main: select error");
				doStop = 1;
				continue;
			}

			if (rc == 0) {
				//logInfo( LOG_CLIENT," __ main: select timeout.\n");
			}

			if ((demuxer != NULL) && (newFileName != NULL) && (demuxer->newProgram == 1)) {
				if (mythGetRecordingDetails(slaveConnection, newFileName) >= 0) {
					demuxer->newProgram = 0;
					programTitle = getStringAtListIndex(slaveConnection->currentRecording, 0);
					logInfo(LOG_CLIENT, "Programname: %s.\n", getStringAtListIndex(slaveConnection->currentRecording, 0));
					osdShowWithTimeoutSeconds(osdTitle, 10, NULL);
				}
			}

			if ((dataAvailable == 1) || (rc > 0)) {

				if (((dataAvailable == 1) || (FD_ISSET(monitorConnection->connection->socket, &working_fd_set))) && (changingChannel == 0)) {

					bytesRead = readResponse(monitorConnection->connection, &response[0], 6000, 0);
					if (bytesRead > 0) {
						logInfo(LOG_CLIENT, "Response: %s\n", &response[0]);
						// We need to trigger in BACKEND_MESSAGE[]:[]SYSTEM_EVENT REC_STARTED CARDID 29 CHANID 11010 STARTTIME 2013-01-09T20:00:05Z RECSTATUS 0 SENDER xen01[]:[]empty
						if ((checkResponse(&response[0], "BACKEND_MESSAGE[]:[]SYSTEM_EVENT REC_STARTED CARDID") != 0) && (recordingFilename == NULL)) {
							// We have an update see if it is for us.
							tmpDetails = convertStrToList(&response[0], " ");
							if (slaveConnection->recorderId == atoi(getStringAtListIndex(tmpDetails,3))) {  // Check recorderId
								if (firstStartRecording == 1) {

									if (newFileName != NULL) {
										free(newFileName);
										newFileName = NULL;
									}
									newFileName = mythConvertToFilename( getStringAtListIndex(tmpDetails,5), getStringAtListIndex(tmpDetails,7));

									if (slaveConnection->streaming == 0) {

										if (mythGetRecordingDetails(slaveConnection, newFileName) >= 0) {
											programTitle = getStringAtListIndex(slaveConnection->currentRecording, 0);
											logInfo(LOG_CLIENT, "Programname: %s.\n", getStringAtListIndex(slaveConnection->currentRecording, 0));
											osdShowWithTimeoutSeconds(osdTitle, 10, NULL);
										}

										logInfo(LOG_CLIENT, "Going to request file=%s.\n", newFileName);
										slaveConnection->channelId = atoi(getStringAtListIndex(tmpDetails,5));
										slaveConnection->transferConnection = mythPrepareNextProgram(slaveConnection, newFileName); 
										if (slaveConnection->transferConnection != NULL) {
											logInfo( LOG_CLIENT," *********************> starting demuxer thread.\n");
											sleep(3); // We let it sleep for 5 seconds so mythtv can buffer up.
											demuxer = demuxerStart(slaveConnection, showVideo, playAudio, 1, audioPassthrough);
											if (demuxer == NULL) {
												logInfo( LOG_CLIENT," *********************> Error starting demuxer thread.\n");
											}
											else {
												slaveConnection->streaming = 1;
											}
										}
									}
									else {
										logInfo(LOG_CLIENT, "Change of program on same channel. Will tell demuxer it needs to stream from a new file %s.\n", newFileName);
										demuxerSetNextFile(demuxer, newFileName);
									}
									//free(newFileName);
								}
								else {
									// We do this because when the first start recording is seen mythtv is still tuning in on the channel. 
									// And will stop this recording when tuned. Then it will start the real recording. 
									logInfo(LOG_CLIENT, "First startrecording we see. We wait for the next one.\n");
									firstStartRecording++;
								}
							}
							freeList(tmpDetails);

						}
					}
				}

				if (FD_ISSET(STDIN, &working_fd_set)) {
					if (read(STDIN, &stdinBuffer, 1) == 1) {
						logInfo(LOG_CLIENT_DEBUG, "Received character on stdin: %d\n", stdinBuffer);
						if ((stdinBuffer >= 48) && (stdinBuffer <= 57)) { // digit keys 0..9
							newChannel = (newChannel * 10) + (stdinBuffer - 48);
							logInfo(LOG_CLIENT, "newChannel=%d.\n", newChannel);
							osdShowWithTimeoutSeconds(osdTitle, 10, NULL);
						}
						if ((stdinBuffer == 10) && (recordingFilename == NULL)) {
							channelChanged = 0;
							if (newChannel != 0) { // enter key
								// Received enter. Switch to new channel when it is not 0.

								if (newChannel != currentChannel) {
									channelChanged = 1;
								}
								newChannel2 = newChannel;
								newChannel = 0;
							}
							else {
								if (newChannel2 != currentChannel) {
									channelChanged = 1;
								}
							}

							if (channelChanged) {
								// Received enter. Switch to new channel2 .
								logInfo(LOG_CLIENT, "Going to switch to channel %d\n", newChannel2);

								changingChannel = 1;

								demuxerStop(demuxer);
								demuxer = NULL;
								if ((slaveConnection != NULL) && (slaveConnection->streaming == 1)) {
									stopLiveTVStream(slaveConnection);
								}

								destroyMythConnection(slaveConnection);
								firstStartRecording = 0;
								slaveConnection = startLiveTV(masterConnection, newChannel2);
								if (slaveConnection == NULL) {
									error = -1;
									logInfo(LOG_CLIENT, "Error switching to channel %d\n", newChannel2);
								}
								else {
									currentChannel = newChannel2;
									logInfo(LOG_CLIENT, "Switched to channel %d\n", newChannel2);
									logInfo( LOG_CLIENT," slaveConnection ChannelId=%s\n",getStringAtListIndex(slaveConnection->currentRecording,6));
									logInfo( LOG_CLIENT," slaveConnection StartTime=%s\n", getStringAtListIndex(slaveConnection->currentRecording,25));
								}

								changingChannel = 0;
							}
						}

						if (stdinBuffer == 27) {  // ESC key
							osdHide(osdTitle);
							newChannel = 0;
						}

						if (stdinBuffer == 43) {  // + key
							newChannel2 += 1;
							logInfo(LOG_CLIENT, "newChannel2=%d.\n", newChannel2);
						}
						if (stdinBuffer == 45) {  // - key
							newChannel2 -= 1;
							logInfo(LOG_CLIENT, "newChannel2=%d.\n", newChannel2);
						}

						if (stdinBuffer == 113) { // q key for quit
							logInfo(LOG_CLIENT, "Received quit from userconsole.\n");
							doStop = 1;
							continue;
						}
					}
				}			
			}

			if ((osdTitle->visible) && (osdTitle->timeout > 0) && ((nowInMicroseconds() - osdTitle->startTime) >= osdTitle->timeout)) {
				logInfo(LOG_CLIENT, "Hiding osdTitle.\n");
				osdHide(osdTitle);
			}
		}
	}

	demuxerStop(demuxer);
	demuxer = NULL;

	if ((slaveConnection != NULL) && (slaveConnection->streaming == 1)) {
		stopLiveTVStream(slaveConnection);
	}

	destroyMythConnection(masterConnection);
	destroyMythConnection(slaveConnection);

	return 0;
}