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); }
/* * 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; }
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)); }
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"); }
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"); }
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 }
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; }
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"); }
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); }
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; }
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); }
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); }
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); }
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; } }
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; }