/* $Id: radiotext.cpp,v 1.7 2009/10/31 10:11:02 seife Exp $ Neutrino-GUI - DBoxII-Project License: GPL This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 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., 675 Mass Ave, Cambridge, MA 02139, USA ripped from: */ /* * radioaudio.c: A plugin for the Video Disk Recorder * * See the README file for copyright information and how to reach the author. * * This is a "plugin" for the Video Disk Recorder (VDR). * * Written by: Lars Tegeler * * Project's homepage: www.math.uni-paderborn.de/~tegeler/vdr * * Latest version available at: URL * * See the file COPYING for license information. * * Description: * * This Plugin display an background image while the vdr is switcht to radio channels. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if 0 #ifdef HAVE_TRIPLEDRAGON #include #include #define DMXDEV "/dev/" DEVICE_NAME_DEMUX "1" #elif HAVE_DVB_API_VERSION < 3 #include #define DMXDEV "/dev/dvb/card0/demux0" #define DVRDEV "/dev/dvb/card0/dvr0" #define dmx_pes_filter_params dmxPesFilterParams #define pes_type pesType #else #include #define DMXDEV "/dev/dvb/adapter0/demux0" #define DVRDEV "/dev/dvb/adapter0/dvr0" #endif #endif #include #include #include #include #include "radiotext.h" #include "radiotools.h" rtp_classes rtp_content; // RDS rest bool RDS_PSShow = false; int RDS_PSIndex = 0; char RDS_PSText[12][9]; // plugin audiorecorder service bool ARec_Receive = false, ARec_Record = false; #if ENABLE_RASS // ... Gallery (1..999) #define RASS_GALMAX 999 bool Rass_Gallery[RASS_GALMAX+1]; int Rass_GalStart, Rass_GalEnd, Rass_GalCount, Rass_SlideFoto; #endif #define floor const char *DataDir = "./"; //cRadioAudio *RadioAudio; //cRadioTextOsd *RadioTextOsd; //cRDSReceiver *RDSReceiver; // RDS-Chartranslation: 0x80..0xff unsigned char rds_addchar[128] = { 0xe1, 0xe0, 0xe9, 0xe8, 0xed, 0xec, 0xf3, 0xf2, 0xfa, 0xf9, 0xd1, 0xc7, 0x8c, 0xdf, 0x8e, 0x8f, 0xe2, 0xe4, 0xea, 0xeb, 0xee, 0xef, 0xf4, 0xf6, 0xfb, 0xfc, 0xf1, 0xe7, 0x9c, 0x9d, 0x9e, 0x9f, 0xaa, 0xa1, 0xa9, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xa3, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xba, 0xb9, 0xb2, 0xb3, 0xb1, 0xa1, 0xb6, 0xb7, 0xb5, 0xbf, 0xf7, 0xb0, 0xbc, 0xbd, 0xbe, 0xa7, 0xc1, 0xc0, 0xc9, 0xc8, 0xcd, 0xcc, 0xd3, 0xd2, 0xda, 0xd9, 0xca, 0xcb, 0xcc, 0xcd, 0xd0, 0xcf, 0xc2, 0xc4, 0xca, 0xcb, 0xce, 0xcf, 0xd4, 0xd6, 0xdb, 0xdc, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xc3, 0xc5, 0xc6, 0xe3, 0xe4, 0xdd, 0xd5, 0xd8, 0xde, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xf0, 0xe3, 0xe5, 0xe6, 0xf3, 0xf4, 0xfd, 0xf5, 0xf8, 0xfe, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; static const char *entitystr[5] = { "'", "&", ""e;", ">", "<" }; static const char *entitychar[5] = { "'", "&", "\"", ">", "<" }; char *CRadioText::rds_entitychar(char *text) { int i = 0, l, lof, lre, space; char *temp; while (i < 5) { if ((temp = strstr(text, entitystr[i])) != NULL) { if (S_Verbose >= 2) printf("RText-Entity: %s\n", text); l = strlen(entitystr[i]); lof = (temp-text); if (strlen(text) < RT_MEL) { lre = strlen(text) - lof - l; space = 1; } else { lre = RT_MEL - 1 - lof - l; space = 0; } memmove(text+lof, entitychar[i], 1); memmove(text+lof+1, temp+l, lre); if (space != 0) memmove(text+lof+1+lre, " ", l-1); } else i++; } return text; } char* CRadioText::ptynr2string(int nr) { switch (nr) { // Source: http://www.ebu.ch/trev_255-beale.pdf case 0: return tr(const_cast("unknown program type")); case 1: return tr(const_cast("News")); case 2: return tr(const_cast("Current affairs")); case 3: return tr(const_cast("Information")); case 4: return tr(const_cast("Sport")); case 5: return tr(const_cast("Education")); case 6: return tr(const_cast("Drama")); case 7: return tr(const_cast("Culture")); case 8: return tr(const_cast("Science")); case 9: return tr(const_cast("Varied")); case 10: return tr(const_cast("Pop music")); case 11: return tr(const_cast("Rock music")); case 12: return tr(const_cast("M.O.R. music")); case 13: return tr(const_cast("Light classical")); case 14: return tr(const_cast("Serious classical")); case 15: return tr(const_cast("Other music")); // 16-30 "Spares" case 31: return tr(const_cast("Alarm")); default: return const_cast("?"); } } bool CRadioText::DividePes(unsigned char *data, int length, int *substart, int *subend) { int i = *substart; int found = 0; while ((i len) return offset; offset += pesl; /* try to find subpackets in the pes stream */ int substart = 0; int subend = 0; while (DividePes(&data[0], pesl, &substart, &subend)) { int inner_offset = subend + 1; if (inner_offset < 3) fprintf(stderr, "RT %s: inner_offset < 3 (%d)\n", __FUNCTION__, inner_offset); int rdsl = data[subend - 1]; // RDS DataFieldLength // RDS DataSync = 0xfd @ end if (data[subend] == 0xfd && rdsl > 0) { // print RawData with RDS-Info if (S_Verbose >= 3) { printf("\n\nPES-Data(%d/%d): ", pesl, len); for (int a=inner_offset -rdsl; a subend - 2 - rdsl; i--) { // <-- data reverse, from end to start if (i < 0) { fprintf(stderr, "RT %s: i < 0 (%d)\n", __FUNCTION__, i); break; } val = data[i]; if (val == 0xfe) { // Start index = -1; rt_start = true; rt_bstuff = false; if (S_Verbose >= 2) printf("RDS-Start: "); } if (rt_start) { if (S_Verbose >= 3) printf("%02x ", val); // byte-stuffing reverse: 0xfd00->0xfd, 0xfd01->0xfe, 0xfd02->0xff if (rt_bstuff) { switch (val) { case 0x00: mtext[index] = 0xfd; break; case 0x01: mtext[index] = 0xfe; break; case 0x02: mtext[index] = 0xff; break; default: mtext[++index] = val; // should never be } rt_bstuff = false; if (S_Verbose >= 3) printf("(Bytestuffing -> %02x) ", mtext[index]); } else mtext[++index] = val; if (val == 0xfd && index > 0) // stuffing found rt_bstuff = true; // early check for used MEC if (index == 5) { //mec = val; switch (val) { case 0x0a: // RT have_radiotext = true; case 0x46: // RTplus-Tags case 0xda: // RASS case 0x07: // PTY case 0x3e: // PTYN case 0x02: // PS mec = val; break; default: rt_start = false; if (S_Verbose >= 2) printf("(RDS-MEC '%02x' not used -> End)\n", val); } } if (index >= mframel) { // max. rdslength, garbage ? if (S_Verbose >= 1) printf("RDS-Error: too long, garbage ?\n"); rt_start = false; } } if (rt_start && val == 0xff) { // End if (S_Verbose >= 2) printf("(RDS-End)\n"); rt_start = false; if (index < 9) { // min. rdslength, garbage ? if (S_Verbose >= 1) printf("RDS-Error: too short -> garbage ?\n"); } else { // crc16-check unsigned short crc16 = crc16_ccitt(mtext, index-3, true); if (crc16 != (mtext[index-2]<<8)+mtext[index-1]) { if (S_Verbose >= 1) printf("RDS-Error: wrong CRC # calc = %04x <> transmit = %02x%02x\n", crc16, mtext[index-2], mtext[index-1]); } else { switch (mec) { case 0x0a: case 0x46: if (S_Verbose >= 2) printf("(RDS-MEC '%02x') -> RadiotextDecode - %d\n", mec, index); RadiotextDecode(mtext, index); // Radiotext, RT+ break; case 0x07: RT_PTY = mtext[8]; // PTY RT_MsgShow = true; if (S_Verbose >= 1) printf("RDS-PTY set to '%s'\n", ptynr2string(RT_PTY)); break; case 0x3e: if (S_Verbose >= 2) printf("(RDS-MEC '%02x') -> RDS_PsPtynDecode - %d\n", mec, index); RDS_PsPtynDecode(true, mtext, index); // PTYN break; case 0x02: if (S_Verbose >= 2) printf("(RDS-MEC '%02x') -> RDS_PsPtynDecode - %d\n", mec, index); RDS_PsPtynDecode(false, mtext, index); // PS break; case 0xda: #if ENABLE_RASS RassDecode(mtext, index); // Rass #endif break; } } } } } } substart = subend; } } } void CRadioText::RadiotextDecode(unsigned char *mtext, int len) { static bool rtp_itoggle = false; static int rtp_idiffs = 0; static cTimeMs rtp_itime; static char plustext[RT_MEL]; // byte 1+2 = ADD (10bit SiteAdress + 6bit EncoderAdress) // byte 3 = SQC (Sequence Counter 0x00 = not used) int leninfo = mtext[4]; // byte 4 = MFL (Message Field Length) if (len >= leninfo+7) { // check complete length // byte 5 = MEC (Message Element Code, 0x0a for RT, 0x46 for RTplus) if (mtext[5] == 0x0a) { // byte 6+7 = DSN+PSN (DataSetNumber+ProgramServiceNumber, // ignore here, always 0x00 ?) // byte 8 = MEL (MessageElementLength, max. 64+1 byte @ RT) if (mtext[8] == 0 || mtext[8] > RT_MEL || mtext[8] > leninfo-4) { if (S_Verbose >= 1) printf("RT-Error: Length = 0 or not correct !"); return; } // byte 9 = RT-Status bitcodet (0=AB-flagcontrol, 1-4=Transmission-Number, 5+6=Buffer-Config, // ingnored, always 0x01 ?) fprintf(stderr, "MEC=0x%02x DSN=0x%02x PSN=0x%02x MEL=%02d STATUS=0x%02x MFL=%02d\n", mtext[5], mtext[6], mtext[7], mtext[8], mtext[9], mtext[4]); char temptext[RT_MEL]; memset(temptext, 0x20, RT_MEL-1); temptext[RT_MEL - 1] = '\0'; for (int i = 1, ii = 0; i < mtext[8]; i++) { if (mtext[9+i] <= 0xfe) // additional rds-character, see RBDS-Standard, Annex E temptext[ii++] = (mtext[9+i] >= 0x80) ? rds_addchar[mtext[9+i]-0x80] : mtext[9+i]; } memcpy(plustext, temptext, RT_MEL); rds_entitychar(temptext); // check repeats bool repeat = false; for (int ind = 0; ind < S_RtOsdRows; ind++) { if (memcmp(RT_Text[ind], temptext, RT_MEL-1) == 0) { repeat = true; if (S_Verbose >= 1) printf("RText-Rep[%d]: %s\n", ind, RT_Text[ind]); } } if (!repeat) { memcpy(RT_Text[RT_Index], temptext, RT_MEL); // +Memory char *temp; asprintf(&temp, "%s", RT_Text[RT_Index]); if (++rtp_content.rt_Index >= 2*MAX_RTPC) rtp_content.rt_Index = 0; asprintf(&rtp_content.radiotext[rtp_content.rt_Index], "%s", rtrim(temp)); free(temp); if (S_Verbose >= 1) printf("Radiotext[%d]: %s\n", RT_Index, RT_Text[RT_Index]); RT_Index +=1; if (RT_Index >= S_RtOsdRows) RT_Index = 0; } RTP_TToggle = 0x03; // Bit 0/1 = Title/Artist RT_MsgShow = true; S_RtOsd = 1; RT_Info = (RT_Info > 0) ? RT_Info : 1; RadioStatusMsg(); } else if (RTP_TToggle > 0 && mtext[5] == 0x46 && S_RtFunc >= 2) { // RTplus tags V2.0, only if RT if (mtext[6] > leninfo-2 || mtext[6] != 8) { // byte 6 = MEL, only 8 byte for 2 tags if (S_Verbose >= 1) printf("RTp-Error: Length not correct !"); return; } uint rtp_typ[2], rtp_start[2], rtp_len[2]; // byte 7+8 = ApplicationID, always 0x4bd7 // byte 9 = Applicationgroup Typecode / PTY ? // bit 10#4 = Item Togglebit // bit 10#3 = Item Runningbit // Tag1: bit 10#2..11#5 = Contenttype, 11#4..12#7 = Startmarker, 12#6..12#1 = Length rtp_typ[0] = (0x38 & mtext[10]<<3) | mtext[11]>>5; rtp_start[0] = (0x3e & mtext[11]<<1) | mtext[12]>>7; rtp_len[0] = 0x3f & mtext[12]>>1; // Tag2: bit 12#0..13#3 = Contenttype, 13#2..14#5 = Startmarker, 14#4..14#0 = Length(5bit) rtp_typ[1] = (0x20 & mtext[12]<<5) | mtext[13]>>3; rtp_start[1] = (0x38 & mtext[13]<<3) | mtext[14]>>5; rtp_len[1] = 0x1f & mtext[14]; if (S_Verbose >= 2) printf("RTplus (tag=Typ/Start/Len): Toggle/Run = %d/%d, tag#1 = %d/%d/%d, tag#2 = %d/%d/%d\n", (mtext[10]&0x10)>0, (mtext[10]&0x08)>0, rtp_typ[0], rtp_start[0], rtp_len[0], rtp_typ[1], rtp_start[1], rtp_len[1]); // save info for (int i = 0; i < 2; i++) { if (rtp_start[i]+rtp_len[i]+1 >= RT_MEL) { // length-error if (S_Verbose >= 1) printf("RTp-Error (tag#%d = Typ/Start/Len): %d/%d/%d (Start+Length > 'RT-MEL' !)\n", i+1, rtp_typ[i], rtp_start[i], rtp_len[i]); } else { char temptext[RT_MEL]; memset(temptext, 0x20, RT_MEL-1); memmove(temptext, plustext+rtp_start[i], rtp_len[i]+1); rds_entitychar(temptext); // +Memory memset(rtp_content.temptext, 0x20, RT_MEL-1); memcpy(rtp_content.temptext, temptext, RT_MEL-1); switch (rtp_typ[i]) { case 1: // Item-Title if ((mtext[10] & 0x08) > 0 && (RTP_TToggle & 0x01) == 0x01) { RTP_TToggle -= 0x01; RT_Info = 2; if (memcmp(RTP_Title, temptext, RT_MEL-1) != 0 || (mtext[10] & 0x10) != RTP_ItemToggle) { memcpy(RTP_Title, temptext, RT_MEL-1); if (RT_PlusShow && rtp_itime.Elapsed() > 1000) rtp_idiffs = (int) rtp_itime.Elapsed()/1000; if (!rtp_content.item_New) { RTP_Starttime = time(NULL); rtp_itime.Set(0); sprintf(RTP_Artist, "---"); if (++rtp_content.item_Index >= MAX_RTPC) rtp_content.item_Index = 0; rtp_content.item_Start[rtp_content.item_Index] = time(NULL); // todo: replay-mode rtp_content.item_Artist[rtp_content.item_Index] = NULL; } rtp_content.item_New = (!rtp_content.item_New) ? true : false; if (rtp_content.item_Index >= 0) asprintf(&rtp_content.item_Title[rtp_content.item_Index], "%s", rtrim(rtp_content.temptext)); RT_PlusShow = RT_MsgShow = rtp_itoggle = true; } } break; case 4: // Item-Artist if ((mtext[10] & 0x08) > 0 && (RTP_TToggle & 0x02) == 0x02) { RTP_TToggle -= 0x02; RT_Info = 2; if (memcmp(RTP_Artist, temptext, RT_MEL-1) != 0 || (mtext[10] & 0x10) != RTP_ItemToggle) { memcpy(RTP_Artist, temptext, RT_MEL-1); if (RT_PlusShow && rtp_itime.Elapsed() > 1000) rtp_idiffs = (int) rtp_itime.Elapsed()/1000; if (!rtp_content.item_New) { RTP_Starttime = time(NULL); rtp_itime.Set(0); sprintf(RTP_Title, "---"); if (++rtp_content.item_Index >= MAX_RTPC) rtp_content.item_Index = 0; rtp_content.item_Start[rtp_content.item_Index] = time(NULL); // todo: replay-mode rtp_content.item_Title[rtp_content.item_Index] = NULL; } rtp_content.item_New = (!rtp_content.item_New) ? true : false; if (rtp_content.item_Index >= 0) asprintf(&rtp_content.item_Artist[rtp_content.item_Index], "%s", rtrim(rtp_content.temptext)); RT_PlusShow = RT_MsgShow = rtp_itoggle = true; } } break; case 12: // Info_News asprintf(&rtp_content.info_News, "%s", rtrim(rtp_content.temptext)); break; case 13: // Info_NewsLocal asprintf(&rtp_content.info_NewsLocal, "%s", rtrim(rtp_content.temptext)); break; case 14: // Info_Stockmarket if (++rtp_content.info_StockIndex >= MAX_RTPC) rtp_content.info_StockIndex = 0; asprintf(&rtp_content.info_Stock[rtp_content.info_StockIndex], "%s", rtrim(rtp_content.temptext)); break; case 15: // Info_Sport if (++rtp_content.info_SportIndex >= MAX_RTPC) rtp_content.info_SportIndex = 0; asprintf(&rtp_content.info_Sport[rtp_content.info_SportIndex], "%s", rtrim(rtp_content.temptext)); break; case 16: // Info_Lottery if (++rtp_content.info_LotteryIndex >= MAX_RTPC) rtp_content.info_LotteryIndex = 0; asprintf(&rtp_content.info_Lottery[rtp_content.info_LotteryIndex], "%s", rtrim(rtp_content.temptext)); break; case 24: // Info_DateTime asprintf(&rtp_content.info_DateTime, "%s", rtrim(rtp_content.temptext)); break; case 25: // Info_Weather if (++rtp_content.info_WeatherIndex >= MAX_RTPC) rtp_content.info_WeatherIndex = 0; asprintf(&rtp_content.info_Weather[rtp_content.info_WeatherIndex], "%s", rtrim(rtp_content.temptext)); break; case 26: // Info_Traffic asprintf(&rtp_content.info_Traffic, "%s", rtrim(rtp_content.temptext)); break; case 27: // Info_Alarm asprintf(&rtp_content.info_Alarm, "%s", rtrim(rtp_content.temptext)); break; case 28: // Info_Advert asprintf(&rtp_content.info_Advert, "%s", rtrim(rtp_content.temptext)); break; case 29: // Info_Url asprintf(&rtp_content.info_Url, "%s", rtrim(rtp_content.temptext)); break; case 30: // Info_Other if (++rtp_content.info_OtherIndex >= MAX_RTPC) rtp_content.info_OtherIndex = 0; asprintf(&rtp_content.info_Other[rtp_content.info_OtherIndex], "%s", rtrim(rtp_content.temptext)); break; case 31: // Programme_Stationname.Long asprintf(&rtp_content.prog_Station, "%s", rtrim(rtp_content.temptext)); break; case 32: // Programme_Now asprintf(&rtp_content.prog_Now, "%s", rtrim(rtp_content.temptext)); break; case 33: // Programme_Next asprintf(&rtp_content.prog_Next, "%s", rtrim(rtp_content.temptext)); break; case 34: // Programme_Part asprintf(&rtp_content.prog_Part, "%s", rtrim(rtp_content.temptext)); break; case 35: // Programme_Host asprintf(&rtp_content.prog_Host, "%s", rtrim(rtp_content.temptext)); break; case 36: // Programme_EditorialStaff asprintf(&rtp_content.prog_EditStaff, "%s", rtrim(rtp_content.temptext)); break; case 38: // Programme_Homepage asprintf(&rtp_content.prog_Homepage, "%s", rtrim(rtp_content.temptext)); break; case 39: // Phone_Hotline asprintf(&rtp_content.phone_Hotline, "%s", rtrim(rtp_content.temptext)); break; case 40: // Phone_Studio asprintf(&rtp_content.phone_Studio, "%s", rtrim(rtp_content.temptext)); break; case 44: // Email_Hotline asprintf(&rtp_content.email_Hotline, "%s", rtrim(rtp_content.temptext)); break; case 45: // Email_Studio asprintf(&rtp_content.email_Studio, "%s", rtrim(rtp_content.temptext)); break; } } } // Title-end @ no Item-Running' if ((mtext[10] & 0x08) == 0) { sprintf(RTP_Title, "---"); sprintf(RTP_Artist, "---"); if (RT_PlusShow) { RT_PlusShow = false; rtp_itoggle = true; rtp_idiffs = (int) rtp_itime.Elapsed()/1000; RTP_Starttime = time(NULL); } RT_MsgShow = (RT_Info > 0); rtp_content.item_New = false; } if (rtp_itoggle) { if (S_Verbose >= 1) { struct tm tm_store; struct tm *ts = localtime_r(&RTP_Starttime, &tm_store); if (rtp_idiffs > 0) printf(" StartTime : %02d:%02d:%02d (last Title elapsed = %d s)\n", ts->tm_hour, ts->tm_min, ts->tm_sec, rtp_idiffs); else printf(" StartTime : %02d:%02d:%02d\n", ts->tm_hour, ts->tm_min, ts->tm_sec); printf(" RTp-Title : %s\n RTp-Artist: %s\n", RTP_Title, RTP_Artist); } RTP_ItemToggle = mtext[10] & 0x10; rtp_itoggle = false; rtp_idiffs = 0; RadioStatusMsg(); // AudioRecorderService(); } RTP_TToggle = 0; } } else { if (S_Verbose >= 1) printf("RDS-Error: [RTDecode] Length not correct !\n"); } } void CRadioText::RDS_PsPtynDecode(bool ptyn, unsigned char *mtext, int len) { if (len < 16) return; // decode Text for (int i = 8; i <= 15; i++) { if (mtext[i] <= 0xfe) { // additional rds-character, see RBDS-Standard, Annex E if (!ptyn) RDS_PSText[RDS_PSIndex][i-8] = (mtext[i] >= 0x80) ? rds_addchar[mtext[i]-0x80] : mtext[i]; else RDS_PTYN[i-8] = (mtext[i] >= 0x80) ? rds_addchar[mtext[i]-0x80] : mtext[i]; } } if (S_Verbose >= 1) { if (!ptyn) printf("RDS-PS No= %d, Content[%d]= '%s'\n", mtext[7], RDS_PSIndex, RDS_PSText[RDS_PSIndex]); else printf("RDS-PTYN No= %d, Content= '%s'\n", mtext[7], RDS_PTYN); } if (!ptyn) { RDS_PSIndex += 1; if (RDS_PSIndex >= 12) RDS_PSIndex = 0; RT_MsgShow = RDS_PSShow = true; } } void CRadioText::RadioStatusMsg(void) { /* announce text/items for lcdproc & other */ if (!RT_MsgShow || S_RtMsgItems <= 0) return; if (S_RtMsgItems >= 2) { char temp[100]; int ind = (RT_Index == 0) ? S_RtOsdRows - 1 : RT_Index - 1; strcpy(temp, RT_Text[ind]); printf("RadioStatusMsg = %s\n", temp); // cStatus::MsgOsdTextItem(rtrim(temp), false); } if ((S_RtMsgItems == 1 || S_RtMsgItems >= 3) && ((S_RtOsdTags == 1 && RT_PlusShow) || S_RtOsdTags >= 2)) { // struct tm tm_store; // struct tm *ts = localtime_r(&RTP_Starttime, &tm_store); // cStatus::MsgOsdProgramme(mktime(ts), RTP_Title, RTP_Artist, 0, NULL, NULL); printf("RTP_Title = %s, RTP_Artist = %s\n", RTP_Title, RTP_Artist); } } #if ENABLE_RASS // add of DVB Radio Slides Specification 1.0, 20061228 void CRadioText::RassDecode(unsigned char *mtext, int len) { static uint splfd = 0, spmax = 0, index = 0; static uint afiles, slidenumr, slideelem, filemax, fileoffp; static int filetype, fileoffb; static bool slideshow = false, slidesave = false, slidecan = false, slidedel = false, start = false; static uchar daten[65536]; // mpegs-stills defined <= 50kB FILE *fd; // byte 1+2 = ADD (10bit SiteAdress + 6bit EncoderAdress) // byte 3 = SQC (Sequence Counter 0x00 = not used) // byte 4 = MFL (Message Field Length), if (len >= mtext[4]+7) { // check complete length // byte 5 = MEC (0xda for Rass) // byte 6 = MEL if (mtext[6] == 0 || mtext[6] > mtext[4]-2) { if ((S_Verbose && 0x0f) >= 1) printf("Rass-Error: Length = 0 or not correct !\n"); return; } // byte 7+8 = Service-ID zugehöriger Datenkanal // byte 9-11 = Nummer aktuelles Paket, uint plfd = mtext[11] + mtext[10]*256 + mtext[9]*65536; // byte 12-14 = Anzahl Pakete, uint pmax = mtext[14] + mtext[13]*256 + mtext[12]*65536; // byte 15+16 = Rass-Kennung = Header, if (mtext[15] == 0x40 && mtext[16] == 0xda) { // first // byte 17+18 = Anzahl Dateien im Archiv, afiles = mtext[18] + mtext[17]*256; // byte 19+20 = Slide-Nummer, slidenumr = mtext[20] + mtext[19]*256; // byte 21+22 = Element-Nummer im Slide, slideelem = mtext[22] + mtext[21]*256; // byte 23 = Slide-Steuerbyte, : bit0 = Anzeige, bit1 = Speichern, bit2 = DarfAnzeige bei Senderwechsel, bit3 = Löschen slideshow = mtext[23] & 0x01; slidesave = mtext[23] & 0x02; slidecan = mtext[23] & 0x04; slidedel = mtext[23] & 0x08; // byte 24 = Dateiart, : 0=unbekannt/1=MPEG-Still/2=Definition filetype = mtext[24]; if (filetype != 1 && filetype != 2) { if ((S_Verbose && 0x0f) >= 1) printf("Rass-Error: Filetype unknown !\n"); return; } // byte 25-28 = Dateilänge, filemax = mtext[28] + mtext[27]*256 + mtext[26]*65536 + mtext[25]*65536*256; if (filemax >= 65536) { if ((S_Verbose && 0x0f) >= 1) printf("Rass-Error: Filesize will be too big !\n"); return; } // byte 29-31 = Dateioffset Paketnr, fileoffp = mtext[31] + mtext[30]*256 + mtext[29]*65536; // byte 32 = Dateioffset Bytenr, fileoffb = mtext[32]; if (S_Verbose >= 2) printf("Rass-Header: afiles= %d\n slidenumr= %d, slideelem= %d\n slideshow= %d, -save= %d, -canschow= %d, -delete= %d\n filetype= %d, filemax= %d\n fileoffp= %d, fileoffb= %d\n", afiles, slidenumr, slideelem, slideshow, slidesave, slidecan, slidedel, filetype, filemax, fileoffp, fileoffb); if (fileoffp == 0) { // First if (S_Verbose >= 2) printf("Rass-Start@0 ...\n"); start = true; index = 0; for (int i=fileoffb; i < len-2; i++) { if (index < filemax) daten[index++] = mtext[i]; else start = false; } } splfd = plfd; } else if (plfd < pmax && plfd == splfd+1) { // Between splfd = plfd; if (!start && fileoffp == plfd) { // Data start, if (S_Verbose >= 2) printf("Rass-Start@%d ...\n", fileoffp); start = true; index = 0; } else fileoffb = 15; if (start) { for (int i=fileoffb; i < len-2; i++) { if (index < filemax) daten[index++] = mtext[i]; else start = false; } } } else if (plfd == pmax && plfd == splfd+1) { // Last fileoffb = 15; if (start) { for (int i=fileoffb; i < len-4; i++) { if (index <= filemax) daten[index++] = mtext[i]; else { start = false; return; } } if (S_Verbose >= 2) printf("... Rass-End (%d bytes)\n", index); } if (filemax > 0) { // nothing todo, if 0 byte file // crc-check with bytes 'len-4/3' unsigned short crc16 = crc16_ccitt(daten, filemax, false); if (crc16 != (mtext[len-4]<<8)+mtext[len-3]) { if ((S_Verbose && 0x0f) >= 1) printf("Rass-Error: wrong CRC # calc = %04x <> transmit = %02x%02x\n", crc16, mtext[len-4], mtext[len-3]); start = false; return; } } // show & save file ? if (index == filemax) { if (slideshow || (slidecan && Rass_Show == -1)) { if (filetype == 1) { // show only mpeg-still char *filepath; asprintf(&filepath, "%s/%s", DataDir, "Rass_show.mpg"); if ((fd = fopen(filepath, "wb")) != NULL) { fwrite(daten, 1, filemax, fd); //fflush(fd); // for test in replaymode fclose(fd); Rass_Show = 1; if (S_Verbose >= 2) printf("Rass-File: ready for displaying :-)\n"); } else printf("ERROR vdr-radio: writing imagefile failed '%s'", filepath); free(filepath); } } if (slidesave || slidedel || slidenumr < RASS_GALMAX) { // lfd. Fotogallery 100.. ??? if (slidenumr >= 100 && slidenumr < RASS_GALMAX) { (Rass_SlideFoto < RASS_GALMAX) ? Rass_SlideFoto++ : Rass_SlideFoto = 100; slidenumr = Rass_SlideFoto; } // char *filepath; (filetype == 2) ? asprintf(&filepath, "%s/Rass_%d.def", DataDir, slidenumr) : asprintf(&filepath, "%s/Rass_%d.mpg", DataDir, slidenumr); if ((fd = fopen(filepath, "wb")) != NULL) { fwrite(daten, 1, filemax, fd); fclose(fd); if (S_Verbose >= 1) printf("Rass-File: saving '%s'\n", filepath); // archivemarker mpeg-stills if (filetype == 1) { // 0, 1000/1100/1110/1111..9000/9900/9990/9999 if (slidenumr == 0 || slidenumr > RASS_GALMAX) { if (slidenumr == 0) { Rass_Flags[0][0] = !slidedel; (RT_Info > 0) ? : RT_Info = 0; // open RadioTextOsd for ArchivTip } else { int islide = (int) floor(slidenumr/1000); for (int i = 3; i >= 0; i--) { if ((slidenumr % (i==3 ? 1000 : i==2 ? 100 : i==1 ? 10 : 1)) == 0) { Rass_Flags[islide][3-i] = !slidedel; //true; break; } } } } // gallery else { Rass_Gallery[slidenumr] = !slidedel; if (!slidedel && (int)slidenumr > Rass_GalEnd) Rass_GalEnd = slidenumr; if (!slidedel && (Rass_GalStart == 0 || (int)slidenumr < Rass_GalStart)) Rass_GalStart = slidenumr; // counter Rass_GalCount = 0; for (int i = Rass_GalStart; i <= Rass_GalEnd; i++) { if (Rass_Gallery[i]) Rass_GalCount++; } Rass_Flags[10][0] = (Rass_GalCount > 0); } } } else printf("ERROR vdr-radio: writing image/data-file failed '%s'", filepath); free(filepath); } } start = false; splfd = spmax = 0; } else { start = false; splfd = spmax = 0; } } else { start = false; splfd = spmax = 0; if (S_Verbose >= 1) printf("RDS-Error: [Rass] Length not correct !\n"); } } #endif #if 0 void cRadioAudio::EnableRadioTextProcessing(const char *Titel, bool replay) { asprintf(&RT_Titel, "%s", Titel); RT_Replay = replay; ARec_Receive = ARec_Record = false; first_packets = 0; enabled = true; imagedelay = 0; // Radiotext init if (S_RtFunc >= 1) { RT_MsgShow = RT_PlusShow = false; RT_ReOpen = true; RT_OsdTO = false; RT_Index = RT_PTY = RTP_TToggle = 0; RTP_ItemToggle = 1; for (int i = 0; i < 5; i++) memset(RT_Text[i], 0x20, RT_MEL-1); sprintf(RTP_Title, "---"); sprintf(RTP_Artist, "---"); RTP_Starttime = time(NULL); // RDS_PSShow = false; RDS_PSIndex = 0; for (int i = 0; i < 12; i++) memset(RDS_PSText[i], 0x20, 8); } // ...Memory rtp_content.start = time(NULL); rtp_content.item_New = false; rtp_content.rt_Index = -1; rtp_content.item_Index = -1; rtp_content.info_StockIndex = -1; rtp_content.info_SportIndex = -1; rtp_content.info_LotteryIndex = -1; rtp_content.info_WeatherIndex = -1; rtp_content.info_OtherIndex = -1; for (int i = 0; i < MAX_RTPC; i++) { rtp_content.radiotext[i] = NULL; rtp_content.radiotext[MAX_RTPC+i] = NULL; rtp_content.item_Title[i] = NULL; rtp_content.item_Artist[i] = NULL; rtp_content.info_Stock[i] = NULL; rtp_content.info_Sport[i] = NULL; rtp_content.info_Lottery[i] = NULL; rtp_content.info_Weather[i] = NULL; rtp_content.info_Other[i] = NULL; } rtp_content.info_News = NULL; rtp_content.info_NewsLocal = NULL; rtp_content.info_DateTime = NULL; rtp_content.info_Traffic = NULL; rtp_content.info_Alarm = NULL; rtp_content.info_Advert = NULL; rtp_content.info_Url = NULL; rtp_content.prog_Station = NULL; rtp_content.prog_Now = NULL; rtp_content.prog_Next = NULL; rtp_content.prog_Part = NULL; rtp_content.prog_Host = NULL; rtp_content.prog_EditStaff = NULL; rtp_content.prog_Homepage = NULL; rtp_content.phone_Hotline = NULL; rtp_content.phone_Studio = NULL; rtp_content.email_Hotline = NULL; rtp_content.email_Studio = NULL; // Rass init Rass_Show = Rass_Archiv = -1; for (int i = 0; i <= 10; i++) { for (int ii = 0; ii < 4; ii++) Rass_Flags[i][ii] = false; } Rass_GalStart = Rass_GalEnd = Rass_GalCount = 0; for (int i = 0; i < RASS_GALMAX; i++) Rass_Gallery[i] = false; Rass_SlideFoto = 99; if (S_RtFunc < 1) return; // RDS-Receiver for seperate Data-PIDs, only Livemode, hardcoded Astra_19E + Hotbird 13E int pid = 0; if (!replay) { switch (chan->Tid()) { case 1113: switch (pid = chan->Apid(0)) { // Astra_19.2E - 12633 GHz /* case 0x161: pid = 0x229; // radio top40 break; */ case 0x400: // Hitradio FFH case 0x406: // planet radio case 0x40c: pid += 1; // harmony.ffm break; default: return; } break; case 1115: switch (pid = chan->Apid(0)) { // Astra_19.2E - 12663 GHz case 0x1bA: pid = 0x21e; // TruckRadio, only NaviData(0xbf) seen break; default: return; } break; case 5300: switch (pid = chan->Apid(0)) { // Hotbird_13E - 11747 GHz, no Radiotext @ moment, only TMC + MECs 25/26 case 0xdc3: // Radio 1 case 0xdd3: // Radio 3 case 0xddb: // Radio 5 case 0xde3: // Radio Exterior case 0xdeb: pid += 1; // Radio 4 break; default: return; } break; default: return; } RDSReceiver = new cRDSReceiver(pid); rdsdevice = cDevice::ActualDevice(); rdsdevice->AttachReceiver(RDSReceiver); } } void cRadioAudio::DisableRadioTextProcessing() { RT_Replay = enabled = false; // Radiotext & Rass RT_Info = -1; RT_ReOpen = false; Rass_Show = Rass_Archiv = -1; Rass_GalStart = Rass_GalEnd = Rass_GalCount = 0; if (RadioTextOsd != NULL) RadioTextOsd->Hide(); if (RDSReceiver != NULL) { rdsdevice->Detach(RDSReceiver); delete RDSReceiver; RDSReceiver = NULL; rdsdevice = NULL; } } // --- cRadioTextOsd ------------------------------------------------------ cBitmap cRadioTextOsd::rds(rds_xpm); cBitmap cRadioTextOsd::arec(arec_xpm); cBitmap cRadioTextOsd::rass(rass_xpm); cBitmap cRadioTextOsd::index(index_xpm); cBitmap cRadioTextOsd::marker(marker_xpm); cBitmap cRadioTextOsd::page1(page1_xpm); cBitmap cRadioTextOsd::pages2(pages2_xpm); cBitmap cRadioTextOsd::pages3(pages3_xpm); cBitmap cRadioTextOsd::pages4(pages4_xpm); cBitmap cRadioTextOsd::no0(no0_xpm); cBitmap cRadioTextOsd::no1(no1_xpm); cBitmap cRadioTextOsd::no2(no2_xpm); cBitmap cRadioTextOsd::no3(no3_xpm); cBitmap cRadioTextOsd::no4(no4_xpm); cBitmap cRadioTextOsd::no5(no5_xpm); cBitmap cRadioTextOsd::no6(no6_xpm); cBitmap cRadioTextOsd::no7(no7_xpm); cBitmap cRadioTextOsd::no8(no8_xpm); cBitmap cRadioTextOsd::no9(no9_xpm); cBitmap cRadioTextOsd::bok(bok_xpm); cBitmap cRadioTextOsd::pageE(pageE_xpm); cRadioTextOsd::cRadioTextOsd() { RadioTextOsd = this; osd = NULL; qosd = NULL; rtclosed = rassclosed = false; RT_ReOpen = false; } cRadioTextOsd::~cRadioTextOsd() { if (Rass_Archiv >= 0) { if (!RT_Replay) Rass_Archiv = RassImage(-1, -1, false); else { Rass_Archiv = -1; RadioAudio->SetBackgroundImage(ReplayFile); } } if (osd != NULL) delete osd; if (qosd != NULL) delete qosd; RadioTextOsd = NULL; RT_ReOpen = !RT_OsdTO; cRemote::Put(LastKey); } void cRadioTextOsd::Show(void) { LastKey = kNone; RT_OsdTO = false; #ifndef VDRP_CLOSEMENU osdtimer.Set(); #endif ftitel = cFont::GetFont(fontOsd); ftext = cFont::GetFont(fontSml); fheight = ftext->Height() + 4; int rowoffset = (S_RtOsdTitle == 1) ? 1 : 0; bheight = (S_RtOsdTags >=1 ) ? fheight * (S_RtOsdRows+rowoffset+2) : fheight * (S_RtOsdRows+rowoffset); (S_RtOsdTitle == 1) ? bheight += 20 : bheight += 12; asprintf(&RTp_Titel, "%s - %s", tr("RTplus"), RT_Titel); if (S_RtDispl >= 1 && (Rass_Show == -1 || S_RassText >= 2)) { RT_MsgShow = (RT_Info >= 1); ShowText(); } } void cRadioTextOsd::Hide(void) { RTOsdClose(); RassOsdClose(); } void cRadioTextOsd::RTOsdClose(void) { if (osd != NULL) { delete osd; osd = NULL; } } #endif #if ENABLE_RASS int CRadioText::RassImage(int QArchiv, int QKey, bool DirUp) { int i; if (QKey >= 0 && QKey <= 9) { if (QArchiv == 0) (Rass_Flags[QKey][0]) ? QArchiv = QKey * 1000 : QArchiv = 0; else if (QArchiv > 0) { if (floor(QArchiv/1000) == QKey) { for (i = 3; i >= 0; i--) { // if (fmod(QArchiv, pow(10, i)) == 0) if ((QArchiv % (i==3 ? 1000 : i==2 ? 100 : i==1 ? 10 : 1)) == 0) break; } if (i > 0) { --i; QArchiv += QKey * (int) (i==3 ? 1000 : i==2 ? 100 : i==1 ? 10 : 1); } else QArchiv = QKey * 1000; (Rass_Flags[QKey][3-i]) ? : QArchiv = QKey * 1000; } else (Rass_Flags[QKey][0]) ? QArchiv = QKey * 1000 : QArchiv = 0; } } // Gallery else if (QKey > 9 && Rass_GalCount >= 0) { if (QArchiv < Rass_GalStart || QArchiv > Rass_GalEnd) QArchiv = Rass_GalStart - 1; if (DirUp) { for (i = QArchiv+1; i <= Rass_GalEnd; i++) { if (Rass_Gallery[i]) break; } QArchiv = (i <= Rass_GalEnd) ? i : Rass_GalStart; } else { for (i = QArchiv-1; i >= Rass_GalStart; i--) { if (Rass_Gallery[i]) break; } QArchiv = (i >= Rass_GalStart) ? i : Rass_GalEnd; } } // show mpeg-still char *image; if (QArchiv >= 0) asprintf(&image, "%s/Rass_%d.mpg", DataDir, QArchiv); else asprintf(&image, "%s/Rass_show.mpg", DataDir); // Houdini: SetBackgroundImage() does not accept mpg stills // frameBuffer->useBackground(frameBuffer->loadBackground(image));// set useBackground true or false // frameBuffer->paintBackground(); // RadioAudio->SetBackgroundImage(image); free(image); return QArchiv; } #endif #if 0 void cRadioTextOsd::RassOsd(void) { int fh = ftext->Height(); if (!qosd && !osd && !Skins.IsOpen() && !cOsd::IsOpen()) { qosd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop+Setup.OSDHeight - (29+264-6+36)); tArea Area = {0, 0, 97, 29+264+5, 4}; qosd->SetAreas(&Area, 1); } if (qosd) { uint32_t bcolor, fcolor; int skin = theme_skin(); // Logo bcolor = radioSkin[skin].clrTitleBack; fcolor = radioSkin[skin].clrTitleText; qosd->DrawRectangle(0, 1, 97, 29, bcolor); qosd->DrawBitmap(25, 5, rass, bcolor, fcolor); // Body bcolor = radioSkin[skin].clrBack; fcolor = radioSkin[skin].clrText; int offs = 29 + 2; qosd->DrawRectangle(0, offs, 97, 29+264+5, bcolor); // Keys+Index offs += 4; qosd->DrawBitmap(4, offs, no0, bcolor, fcolor); qosd->DrawBitmap(44, offs, index, bcolor, fcolor); qosd->DrawBitmap(4, 24+offs, no1, bcolor, fcolor); qosd->DrawBitmap(4, 48+offs, no2, bcolor, fcolor); qosd->DrawBitmap(4, 72+offs, no3, bcolor, fcolor); qosd->DrawBitmap(4, 96+offs, no4, bcolor, fcolor); qosd->DrawBitmap(4, 120+offs, no5, bcolor, fcolor); qosd->DrawBitmap(4, 144+offs, no6, bcolor, fcolor); qosd->DrawBitmap(4, 168+offs, no7, bcolor, fcolor); qosd->DrawBitmap(4, 192+offs, no8, bcolor, fcolor); qosd->DrawBitmap(4, 216+offs, no9, bcolor, fcolor); qosd->DrawBitmap(4, 240+offs, bok, bcolor, fcolor); // Content bool mark = false; for (int i = 1; i <= 9; i++) { // Pages if (Rass_Flags[i][0] && Rass_Flags[i][1] && Rass_Flags[i][2] && Rass_Flags[i][3]) qosd->DrawBitmap(48, (i*24)+offs, pages4, bcolor, fcolor); else if (Rass_Flags[i][0] && Rass_Flags[i][1] && Rass_Flags[i][2]) qosd->DrawBitmap(48, (i*24)+offs, pages3, bcolor, fcolor); else if (Rass_Flags[i][0] && Rass_Flags[i][1]) qosd->DrawBitmap(48, (i*24)+offs, pages2, bcolor, fcolor); else if (Rass_Flags[i][0]) qosd->DrawBitmap(48, (i*24)+offs, page1, bcolor, fcolor); // Marker if (floor(Rass_Archiv/1000) == i) { qosd->DrawBitmap(28, (i*24)+offs, marker, bcolor, fcolor); mark = true; } } // Gallery if (Rass_GalCount > 0) { char *temp; qosd->DrawBitmap(48, 240+offs, pageE, bcolor, fcolor); asprintf(&temp, "%d", Rass_GalCount); qosd->DrawText(67, 240+offs-2, temp, fcolor, clrTransparent, ftext, 97, fh); free(temp); } // Marker gallery/index if (!mark) { if (Rass_Archiv > 0 && Rass_Archiv <= RASS_GALMAX) qosd->DrawBitmap(30, 240+offs, marker, bcolor, fcolor); else qosd->DrawBitmap(28, offs, marker, bcolor, fcolor); } qosd->Flush(); } } void cRadioTextOsd::RassOsdTip(void) { int fh = ftext->Height(); if (!qosd && !osd && !Skins.IsOpen() && !cOsd::IsOpen()) { qosd = cOsdProvider::NewOsd(Setup.OSDLeft, Setup.OSDTop+Setup.OSDHeight - (29+(2*fh)-6+36)); tArea Area = {0, 0, 97, 29+(2*fh)+5, 4}; qosd->SetAreas(&Area, 1); } if (qosd) { uint32_t bcolor, fcolor; int skin = theme_skin(); // Title bcolor = radioSkin[skin].clrTitleBack; fcolor = radioSkin[skin].clrTitleText; qosd->DrawRectangle(0, 0, 97, 29, bcolor); qosd->DrawBitmap(25, 5, rass, bcolor, fcolor); // Body bcolor = radioSkin[skin].clrBack; fcolor = radioSkin[skin].clrText; qosd->DrawRectangle(0, 29+2, 97, 29+(2*fh)+5, bcolor); qosd->DrawText(5, 29+4, tr("Records"), fcolor, clrTransparent, ftext, 97, fh); qosd->DrawText(5, 29+fh+4, tr("with <0>"), fcolor, clrTransparent, ftext, 97, fh); qosd->Flush(); } } void cRadioTextOsd::RassOsdClose(void) { if (qosd != NULL) { delete qosd; qosd = NULL; } } void cRadioTextOsd::RassImgSave(char *size, int pos) { char *infile, *outfile, *cmd; int filenr = 0, error = 0; struct tm *ts, tm_store; time_t t = time(NULL); ts = localtime_r(&t, &tm_store); switch (pos) { // all from 1-9 case 1 ... 9: for (int i = 3; i >= 0; i--) { filenr += (int) (pos * pow(10, i)); if (Rass_Flags[pos][3-i]) { asprintf(&infile, "%s/Rass_%d.mpg", DataDir, filenr); asprintf(&outfile, "%s/Rass_%s-%04d_%02d%02d%02d%02d.jpg", DataDir, RT_Titel, filenr, ts->tm_mon+1, ts->tm_mday, ts->tm_hour, ts->tm_min); asprintf(&cmd, "ffmpeg -i %s -s %s -f mjpeg -y %s", infile, size, outfile); if ((error = system(cmd))) i = -1; } } asprintf(&cmd, "%s '%d'", tr("Rass-Image(s) saved from Archiv "), pos); break; // all from gallery case 10: for (int i = Rass_GalStart; i <= Rass_GalEnd; i++) { if (Rass_Gallery[i]) { asprintf(&infile, "%s/Rass_%d.mpg", DataDir, i); asprintf(&outfile, "%s/Rass_%s-Gallery%04d_%02d%02d.jpg", DataDir, RT_Titel, i, ts->tm_mon+1, ts->tm_mday); asprintf(&cmd, "ffmpeg -i %s -s %s -f mjpeg -y %s", infile, size, outfile); if ((error = system(cmd))) i = Rass_GalEnd + 1; } } asprintf(&cmd, "%s", tr("Rass-Image(s) saved from Gallery")); break; // single default: asprintf(&infile, "%s/Rass_%d.mpg", DataDir, Rass_Archiv); asprintf(&outfile, "%s/Rass_%s-%04d_%02d%02d%02d%02d.jpg", DataDir, RT_Titel, Rass_Archiv, ts->tm_mon+1, ts->tm_mday, ts->tm_hour, ts->tm_min); asprintf(&cmd, "ffmpeg -i %s -s %s -f mjpeg -y %s", infile, size, outfile); error = system(cmd); asprintf(&cmd, "%s: %s", tr("Rass-Image saved"), outfile); } free(infile); // Info RassOsdClose(); if (error) { asprintf(&cmd, "%s: %s", tr("Rass-Image failed"), outfile); Skins.Message(mtError, cmd, Setup.OSDMessageTime); } else Skins.Message(mtInfo, cmd, Setup.OSDMessageTime); free(outfile); free(cmd); } void cRadioTextOsd::rtp_print(void) { struct tm tm_store; time_t t = time(NULL); printf("\n>>> RTplus-Memoryclasses @ %s", asctime(localtime_r(&t, &tm_store))); printf(" on '%s' since %s", RT_Titel, asctime(localtime_r(&rtp_content.start, &tm_store))); printf("--- Programme ---\n"); if (rtp_content.prog_Station != NULL) printf(" Station: %s\n", rtp_content.prog_Station); if (rtp_content.prog_Now != NULL) printf(" Now: %s\n", rtp_content.prog_Now); if (rtp_content.prog_Next != NULL) printf(" Next: %s\n", rtp_content.prog_Next); if (rtp_content.prog_Part != NULL) printf(" Part: %s\n", rtp_content.prog_Part); if (rtp_content.prog_Host != NULL) printf(" Host: %s\n", rtp_content.prog_Host); if (rtp_content.prog_EditStaff != NULL) printf(" Ed.Staff: %s\n", rtp_content.prog_EditStaff); if (rtp_content.prog_Homepage != NULL) printf(" Homepage: %s\n", rtp_content.prog_Homepage); printf("--- Interactivity ---\n"); if (rtp_content.phone_Hotline != NULL) printf(" Phone-Hotline: %s\n", rtp_content.phone_Hotline); if (rtp_content.phone_Studio != NULL) printf(" Phone-Studio: %s\n", rtp_content.phone_Studio); if (rtp_content.email_Hotline != NULL) printf(" Email-Hotline: %s\n", rtp_content.email_Hotline); if (rtp_content.email_Studio != NULL) printf(" Email-Studio: %s\n", rtp_content.email_Studio); printf("--- Info ---\n"); if (rtp_content.info_News != NULL) printf(" News: %s\n", rtp_content.info_News); if (rtp_content.info_NewsLocal != NULL) printf(" NewsLocal: %s\n", rtp_content.info_NewsLocal); if (rtp_content.info_DateTime != NULL) printf(" DateTime: %s\n", rtp_content.info_DateTime); if (rtp_content.info_Traffic != NULL) printf(" Traffic: %s\n", rtp_content.info_Traffic); if (rtp_content.info_Alarm != NULL) printf(" Alarm: %s\n", rtp_content.info_Alarm); if (rtp_content.info_Advert != NULL) printf(" Advertisg: %s\n", rtp_content.info_Advert); if (rtp_content.info_Url != NULL) printf(" Url: %s\n", rtp_content.info_Url); // no sorting for (int i = 0; i < MAX_RTPC; i++) if (rtp_content.info_Stock[i] != NULL) printf(" Stock[%02d]: %s\n", i, rtp_content.info_Stock[i]); for (int i = 0; i < MAX_RTPC; i++) if (rtp_content.info_Sport[i] != NULL) printf(" Sport[%02d]: %s\n", i, rtp_content.info_Sport[i]); for (int i = 0; i < MAX_RTPC; i++) if (rtp_content.info_Lottery[i] != NULL) printf(" Lottery[%02d]: %s\n", i, rtp_content.info_Lottery[i]); for (int i = 0; i < MAX_RTPC; i++) if (rtp_content.info_Weather[i] != NULL) printf(" Weather[%02d]: %s\n", i, rtp_content.info_Weather[i]); for (int i = 0; i < MAX_RTPC; i++) if (rtp_content.info_Other[i] != NULL) printf(" Other[%02d]: %s\n", i, rtp_content.info_Other[i]); /* printf("--- Item-Playlist ---\n"); // no sorting if (rtp_content.item_Index >= 0) { for (int i = 0; i < MAX_RTPC; i++) { if (rtp_content.item_Title[i] != NULL && rtp_content.item_Artist[i] != NULL) { struct tm tm_store; struct tm *ts = localtime_r(&rtp_content.item_Start[i], &tm_store); printf(" [%02d] %02d:%02d Title: %s | Artist: %s\n", i, ts->tm_hour, ts->tm_min, rtp_content.item_Title[i], rtp_content.item_Artist[i]); } } } printf("--- Last seen Radiotext ---\n"); // no sorting if (rtp_content.rt_Index >= 0) { for (int i = 0; i < 2*MAX_RTPC; i++) if (rtp_content.radiotext[i] != NULL) printf(" [%03d] %s\n", i, rtp_content.radiotext[i]); } */ printf("<<<\n"); } #define rtplog 0 eOSState cRadioTextOsd::ProcessKey(eKeys Key) { // RTplus Infolog if (rtplog == 1 && S_Verbose >= 1) { static int ct = 0; if (++ct >= 60) { ct = 0; rtp_print(); } } // check end @ replay if (RT_Replay) { int rplayCur, rplayTot; cControl::Control()->GetIndex(rplayCur, rplayTot, false); if (rplayCur >= rplayTot-1) { Hide(); return osEnd; } } // Timeout or no Info/Rass if (RT_OsdTO || (RT_OsdTOTemp > 0) || (RT_Info < 0)) { Hide(); return osEnd; } eOSState state = cOsdObject::ProcessKey(Key); if (state != osUnknown) return state; // Key pressed ... if (Key != kNone && Key < k_Release) { if (osd) { // Radiotext, -plus Osd switch (Key) { case kBack: RTOsdClose(); rtclosed = true; //rassclosed = false; break; case k0: RTOsdClose(); RTplus_Osd = true; cRemote::CallPlugin("radio"); return osEnd; default: Hide(); LastKey = (Key == kChanUp || Key == kChanDn) ? kNone : Key; return osEnd; } } else if (qosd && Rass_Archiv >= 0) { // Rass-Archiv Osd int i, pos; pos = (Rass_Archiv > 0 && Rass_Archiv <= RASS_GALMAX) ? 10 : (int) floor(Rass_Archiv/1000); switch (Key) { // back to Slideshow case kBlue: case kBack: if (!RT_Replay) Rass_Archiv = RassImage(-1, 0, false); else { Rass_Archiv = -1; RadioAudio->SetBackgroundImage(ReplayFile); } RassOsdClose(); rassclosed = rtclosed = false; break; // Archiv-Sides case k0 ... k9: Rass_Archiv = RassImage(Rass_Archiv, Key-k0, false); RassOsd(); break; case kOk: if (Rass_Flags[10][0]) { Rass_Archiv = RassImage(Rass_Archiv, 10, true); RassOsd(); } break; case kLeft: case kRight: Rass_Archiv = RassImage(Rass_Archiv, pos, (Key == kRight) ? true : false); RassOsd(); break; case kDown: (pos == 10) ? i = 0 : i = pos + 1; while (i != pos) { if (Rass_Flags[i][0]) { Rass_Archiv = RassImage(Rass_Archiv, i, true); RassOsd(); return osContinue; } if (++i > 10) i = 0; } break; case kUp: (pos == 0) ? i = 10 : i = pos - 1; while (i != pos) { if (Rass_Flags[i][0]) { Rass_Archiv = RassImage(Rass_Archiv, i, true); RassOsd(); return osContinue; } if (--i < 0) i = 10; } break; case kRed: RassImgSave("1024x576", 0); break; case kGreen: RassImgSave("1024x576", pos); break; case kYellow: break; // todo, what ? default: Hide(); LastKey = (Key == kChanUp || Key == kChanDn) ? kNone : Key; return osEnd; } } else if (qosd && Rass_Archiv == -1) { // Rass-Slideshow Osd switch (Key) { // close case kBack: RassOsdClose(); rassclosed = true; //rtclosed = false; break; // Archiv-Index case k0: if (Rass_Flags[0][0]) { RassOsdClose(); Rass_Archiv = RassImage(0, 0, false); RassOsd(); } break; default: Hide(); LastKey = (Key == kChanUp || Key == kChanDn) ? kNone : Key; return osEnd; } } else { // no RT && no Rass Hide(); LastKey = (Key == kChanUp || Key == kChanDn) ? kNone : Key; return osEnd; } } // no Key pressed ... #ifndef VDRP_CLOSEMENU else if (S_RtOsdTO > 0 && osdtimer.Elapsed()/1000/60 >= (uint)S_RtOsdTO) { RT_OsdTO = true; Hide(); return osEnd; } #endif else if (Rass_Archiv >= 0) RassOsd(); else if (RT_MsgShow && !rtclosed && (Rass_Show == -1 || S_RassText >= 2 || rassclosed)) { RassOsdClose(); ShowText(); } else if (Rass_Flags[0][0] && !rassclosed && (S_RassText < 2 || rtclosed)) { RTOsdClose(); RassOsdTip(); } return osContinue; } // --- cRTplusOsd ------------------------------------------------------ cRTplusOsd::cRTplusOsd(void) :cOsdMenu(RTp_Titel, 3, 12) { RTplus_Osd = false; bcount = helpmode = 0; listtyp[0] = tr("Radiotext"); listtyp[1] = tr("Playlist"); listtyp[2] = tr("Sports"); listtyp[3] = tr("Lottery"); listtyp[4] = tr("Weather"); listtyp[5] = tr("Stockmarket"); listtyp[6] = tr("Other"); Load(); Display(); } cRTplusOsd::~cRTplusOsd() { } void cRTplusOsd::Load(void) { char text[80]; struct tm tm_store; struct tm *ts = localtime_r(&rtp_content.start, &tm_store); snprintf(text, sizeof(text), "%s %02d:%02d", tr("RTplus Memory since"), ts->tm_hour, ts->tm_min); Add(new cOsdItem(hk(text))); snprintf(text, sizeof(text), "%s", " "); Add(new cOsdItem(hk(text))); snprintf(text, sizeof(text), "-- %s --", tr("Programme")); Add(new cOsdItem(hk(text))); if (rtp_content.prog_Station != NULL) { snprintf(text, sizeof(text), "\t%s:\t%s", tr("Station"), rtp_content.prog_Station); Add(new cOsdItem(hk(text))); } if (rtp_content.prog_Now != NULL) { snprintf(text, sizeof(text), "\t%s:\t%s", tr("Now"), rtp_content.prog_Now); Add(new cOsdItem(hk(text))); } if (rtp_content.prog_Part != NULL) { snprintf(text, sizeof(text), "\t%s:\t%s", tr("...Part"), rtp_content.prog_Part); Add(new cOsdItem(hk(text))); } if (rtp_content.prog_Next != NULL) { snprintf(text, sizeof(text), "\t%s:\t%s", tr("Next"), rtp_content.prog_Next); Add(new cOsdItem(hk(text))); } if (rtp_content.prog_Host != NULL) { snprintf(text, sizeof(text), "\t%s:\t%s", tr("Host"), rtp_content.prog_Host); Add(new cOsdItem(hk(text))); } if (rtp_content.prog_EditStaff != NULL) { snprintf(text, sizeof(text), "\t%s:\t%s", tr("Edit.Staff"), rtp_content.prog_EditStaff); Add(new cOsdItem(hk(text))); } if (rtp_content.prog_Homepage != NULL) { snprintf(text, sizeof(text), "\t%s:\t%s", tr("Homepage"), rtp_content.prog_Homepage); Add(new cOsdItem(hk(text))); } snprintf(text, sizeof(text), "%s", " "); Add(new cOsdItem(hk(text))); snprintf(text, sizeof(text), "-- %s --", tr("Interactivity")); Add(new cOsdItem(hk(text))); if (rtp_content.phone_Hotline != NULL) { snprintf(text, sizeof(text), "\t%s:\t%s", tr("Phone-Hotline"), rtp_content.phone_Hotline); Add(new cOsdItem(hk(text))); } if (rtp_content.phone_Studio != NULL) { snprintf(text, sizeof(text), "\t%s:\t%s", tr("Phone-Studio"), rtp_content.phone_Studio); Add(new cOsdItem(hk(text))); } if (rtp_content.email_Hotline != NULL) { snprintf(text, sizeof(text), "\t%s:\t%s", tr("Email-Hotline"), rtp_content.email_Hotline); Add(new cOsdItem(hk(text))); } if (rtp_content.email_Studio != NULL) { snprintf(text, sizeof(text), "\t%s:\t%s", tr("Email-Studio"), rtp_content.email_Studio); Add(new cOsdItem(hk(text))); } snprintf(text, sizeof(text), "%s", " "); Add(new cOsdItem(hk(text))); snprintf(text, sizeof(text), "-- %s --", tr("Info")); Add(new cOsdItem(hk(text))); if (rtp_content.info_News != NULL) { snprintf(text, sizeof(text), "\t%s:\t%s", tr("News"), rtp_content.info_News); Add(new cOsdItem(hk(text))); } if (rtp_content.info_NewsLocal != NULL) { snprintf(text, sizeof(text), "\t%s:\t%s", tr("NewsLocal"), rtp_content.info_NewsLocal); Add(new cOsdItem(hk(text))); } if (rtp_content.info_DateTime != NULL) { snprintf(text, sizeof(text), "\t%s:\t%s", tr("DateTime"), rtp_content.info_DateTime); Add(new cOsdItem(hk(text))); } if (rtp_content.info_Traffic != NULL) { snprintf(text, sizeof(text), "\t%s:\t%s", tr("Traffic"), rtp_content.info_Traffic); Add(new cOsdItem(hk(text))); } if (rtp_content.info_Alarm != NULL) { snprintf(text, sizeof(text), "\t%s:\t%s", tr("Alarm"), rtp_content.info_Alarm); Add(new cOsdItem(hk(text))); } if (rtp_content.info_Advert != NULL) { snprintf(text, sizeof(text), "\t%s:\t%s", tr("Advertising"), rtp_content.info_Advert); Add(new cOsdItem(hk(text))); } if (rtp_content.info_Url != NULL) { snprintf(text, sizeof(text), "\t%s:\t%s", tr("Url"), rtp_content.info_Url); Add(new cOsdItem(hk(text))); } for (int i = 0; i <= 6; i++) btext[i] = NULL; bcount = 0; asprintf(&btext[bcount++], "%s", listtyp[0]); if (rtp_content.item_Index >= 0) asprintf(&btext[bcount++], "%s", listtyp[1]); if (rtp_content.info_SportIndex >= 0) asprintf(&btext[bcount++], "%s", listtyp[2]); if (rtp_content.info_LotteryIndex >= 0) asprintf(&btext[bcount++], "%s", listtyp[3]); if (rtp_content.info_WeatherIndex >= 0) asprintf(&btext[bcount++], "%s", listtyp[4]); if (rtp_content.info_StockIndex >= 0) asprintf(&btext[bcount++], "%s", listtyp[5]); if (rtp_content.info_OtherIndex >= 0) asprintf(&btext[bcount++], "%s", listtyp[6]); switch (bcount) { case 4: if (helpmode == 0) SetHelp(btext[0], btext[1], btext[2], ">>"); else if (helpmode == 1) SetHelp("<<", btext[3], NULL, tr("Exit")); break; case 5: if (helpmode == 0) SetHelp(btext[0], btext[1], btext[2], ">>"); else if (helpmode == 1) SetHelp("<<", btext[3], btext[4], tr("Exit")); break; case 6: if (helpmode == 0) SetHelp(btext[0], btext[1], btext[2], ">>"); else if (helpmode == 1) SetHelp("<<", btext[3], btext[4], ">>"); else if (helpmode == 2) SetHelp("<<", btext[5], NULL, tr("Exit")); break; case 7: if (helpmode == 0) SetHelp(btext[0], btext[1], btext[2], ">>"); else if (helpmode == 1) SetHelp("<<", btext[3], btext[4], ">>"); else if (helpmode == 2) SetHelp("<<", btext[5], btext[6], tr("Exit")); break; default: helpmode = 0; SetHelp(btext[0], btext[1], btext[2], tr("Exit")); } } void cRTplusOsd::Update(void) { Clear(); Load(); Display(); } int cRTplusOsd::rtptyp(char *btext) { for (int i = 0; i <= 6; i++) { if (strcmp(btext, listtyp[i]) == 0) return i; } return -1; } void cRTplusOsd::rtp_fileprint(void) { struct tm *ts, tm_store; char *fname, *fpath; FILE *fd; int ind, lfd = 0; time_t t = time(NULL); ts = localtime_r(&t, &tm_store); asprintf(&fname, "RTplus_%s_%04d-%02d-%02d.%02d.%02d", RT_Titel, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday, ts->tm_hour, ts->tm_min); asprintf(&fpath, "%s/%s", DataDir, fname); if ((fd = fopen(fpath, "w")) != NULL) { fprintf(fd, ">>> RTplus-Memoryclasses @ %s", asctime(localtime_r(&t, &tm_store))); fprintf(fd, " on '%s' since %s", RT_Titel, asctime(localtime_r(&rtp_content.start, &tm_store))); fprintf(fd, "--- Programme ---\n"); if (rtp_content.prog_Station != NULL) fprintf(fd, " Station: %s\n", rtp_content.prog_Station); if (rtp_content.prog_Now != NULL) fprintf(fd, " Now: %s\n", rtp_content.prog_Now); if (rtp_content.prog_Part != NULL) fprintf(fd, " Part: %s\n", rtp_content.prog_Part); if (rtp_content.prog_Next != NULL) fprintf(fd, " Next: %s\n", rtp_content.prog_Next); if (rtp_content.prog_Host != NULL) fprintf(fd, " Host: %s\n", rtp_content.prog_Host); if (rtp_content.prog_EditStaff != NULL) fprintf(fd, " Ed.Staff: %s\n", rtp_content.prog_EditStaff); if (rtp_content.prog_Homepage != NULL) fprintf(fd, " Homepage: %s\n", rtp_content.prog_Homepage); fprintf(fd, "--- Interactivity ---\n"); if (rtp_content.phone_Hotline != NULL) fprintf(fd, " Phone-Hotline: %s\n", rtp_content.phone_Hotline); if (rtp_content.phone_Studio != NULL) fprintf(fd, " Phone-Studio: %s\n", rtp_content.phone_Studio); if (rtp_content.email_Hotline != NULL) fprintf(fd, " Email-Hotline: %s\n", rtp_content.email_Hotline); if (rtp_content.email_Studio != NULL) fprintf(fd, " Email-Studio: %s\n", rtp_content.email_Studio); fprintf(fd, "--- Info ---\n"); if (rtp_content.info_News != NULL) fprintf(fd, " News: %s\n", rtp_content.info_News); if (rtp_content.info_NewsLocal != NULL) fprintf(fd, " NewsLocal: %s\n", rtp_content.info_NewsLocal); if (rtp_content.info_DateTime != NULL) fprintf(fd, " DateTime: %s\n", rtp_content.info_DateTime); if (rtp_content.info_Traffic != NULL) fprintf(fd, " Traffic: %s\n", rtp_content.info_Traffic); if (rtp_content.info_Alarm != NULL) fprintf(fd, " Alarm: %s\n", rtp_content.info_Alarm); if (rtp_content.info_Advert != NULL) fprintf(fd, " Advertisg: %s\n", rtp_content.info_Advert); if (rtp_content.info_Url != NULL) fprintf(fd, " Url: %s\n", rtp_content.info_Url); if (rtp_content.item_Index >= 0) { fprintf(fd, "--- Item-Playlist ---\n"); ind = rtp_content.item_Index; if (ind < (MAX_RTPC-1) && rtp_content.item_Title[ind+1] != NULL) { for (int i = ind+1; i < MAX_RTPC; i++) { if (rtp_content.item_Title[i] != NULL && rtp_content.item_Artist[i] != NULL) { ts = localtime_r(&rtp_content.item_Start[i], &tm_store); fprintf(fd, " %02d:%02d Title: '%s' | Artist: '%s'\n", ts->tm_hour, ts->tm_min, rtp_content.item_Title[i], rtp_content.item_Artist[i]); } } } for (int i = 0; i <= ind; i++) { if (rtp_content.item_Title[i] != NULL && rtp_content.item_Artist[i] != NULL) { ts = localtime_r(&rtp_content.item_Start[i], &tm_store); fprintf(fd, " %02d:%02d Title: '%s' | Artist: '%s'\n", ts->tm_hour, ts->tm_min, rtp_content.item_Title[i], rtp_content.item_Artist[i]); } } } if (rtp_content.info_SportIndex >= 0) { fprintf(fd, "--- Sports ---\n"); ind = rtp_content.info_SportIndex; if (ind < (MAX_RTPC-1) && rtp_content.info_Sport[ind+1] != NULL) { for (int i = ind+1; i < MAX_RTPC; i++) { if (rtp_content.info_Sport[i] != NULL) fprintf(fd, " %02d. %s\n", ++lfd, rtp_content.info_Sport[i]); } } for (int i = 0; i <= ind; i++) { if (rtp_content.info_Sport[i] != NULL) fprintf(fd, " %02d. %s\n", ++lfd, rtp_content.info_Sport[i]); } } if (rtp_content.info_LotteryIndex >= 0) { fprintf(fd, "--- Lottery ---\n"); ind = rtp_content.info_LotteryIndex; if (ind < (MAX_RTPC-1) && rtp_content.info_Lottery[ind+1] != NULL) { for (int i = ind+1; i < MAX_RTPC; i++) { if (rtp_content.info_Lottery[i] != NULL) fprintf(fd, " %02d. %s\n", ++lfd, rtp_content.info_Lottery[i]); } } for (int i = 0; i <= ind; i++) { if (rtp_content.info_Lottery[i] != NULL) fprintf(fd, " %02d. %s\n", ++lfd, rtp_content.info_Lottery[i]); } } if (rtp_content.info_WeatherIndex >= 0) { fprintf(fd, "--- Weather ---\n"); ind = rtp_content.info_WeatherIndex; if (ind < (MAX_RTPC-1) && rtp_content.info_Weather[ind+1] != NULL) { for (int i = ind+1; i < MAX_RTPC; i++) { if (rtp_content.info_Weather[i] != NULL) fprintf(fd, " %02d. %s\n", ++lfd, rtp_content.info_Weather[i]); } } for (int i = 0; i <= ind; i++) { if (rtp_content.info_Weather[i] != NULL) fprintf(fd, " %02d. %s\n", ++lfd, rtp_content.info_Weather[i]); } } if (rtp_content.info_StockIndex >= 0) { fprintf(fd, "--- Stockmarket ---\n"); ind = rtp_content.info_StockIndex; if (ind < (MAX_RTPC-1) && rtp_content.info_Stock[ind+1] != NULL) { for (int i = ind+1; i < MAX_RTPC; i++) { if (rtp_content.info_Stock[i] != NULL) fprintf(fd, " %02d. %s\n", ++lfd, rtp_content.info_Stock[i]); } } for (int i = 0; i <= ind; i++) { if (rtp_content.info_Stock[i] != NULL) fprintf(fd, " %02d. %s\n", ++lfd, rtp_content.info_Stock[i]); } } if (rtp_content.info_OtherIndex >= 0) { fprintf(fd, "--- Other ---\n"); ind = rtp_content.info_OtherIndex; if (ind < (MAX_RTPC-1) && rtp_content.info_Other[ind+1] != NULL) { for (int i = ind+1; i < MAX_RTPC; i++) { if (rtp_content.info_Other[i] != NULL) fprintf(fd, " %02d. %s\n", ++lfd, rtp_content.info_Other[i]); } } for (int i = 0; i <= ind; i++) { if (rtp_content.info_Other[i] != NULL) fprintf(fd, " %02d. %s\n", ++lfd, rtp_content.info_Other[i]); } } fprintf(fd, "--- Last seen Radiotext ---\n"); ind = rtp_content.rt_Index; if (ind < (2*MAX_RTPC-1) && rtp_content.radiotext[ind+1] != NULL) { for (int i = ind+1; i < 2*MAX_RTPC; i++) { if (rtp_content.radiotext[i] != NULL) fprintf(fd, " %03d. %s\n", ++lfd, rtp_content.radiotext[i]); } } for (int i = 0; i <= ind; i++) { if (rtp_content.radiotext[i] != NULL) fprintf(fd, " %03d. %s\n", ++lfd, rtp_content.radiotext[i]); } fprintf(fd, "<<<\n"); fclose(fd); char *infotext; asprintf(&infotext, "%s: %s", tr("RTplus-File saved"), fname); Skins.Message(mtInfo, infotext, Setup.OSDMessageTime); free(infotext); } else printfesyslog("ERROR vdr-radio: writing RTplus-File failed '%s'", fpath); free(fpath); free(fname); } eOSState cRTplusOsd::ProcessKey(eKeys Key) { int typ, ind; eOSState state = cOsdMenu::ProcessKey(Key); if (HasSubMenu()) return osContinue; if (state == osUnknown) { switch (Key) { case kBack: case kOk: return osEnd; case kBlue: if (bcount >= 4 && helpmode == 0) { helpmode += 1; Update(); } else if (bcount >= 6 && helpmode == 1) { helpmode += 1; Update(); } else return osEnd; break; case k0: Update(); break; case k8: rtp_fileprint(); break; case kRed: if (helpmode == 0) { if (btext[0] != NULL) if ((typ = rtptyp(btext[0])) >= 0) AddSubMenu(new cRTplusList(typ)); } else { helpmode -= 1; Update(); } break; case kGreen: ind = (helpmode*2) + 1; if (btext[ind] != NULL) { if ((typ = rtptyp(btext[ind])) >= 0) AddSubMenu(new cRTplusList(typ)); } break; case kYellow: ind = (helpmode*2) + 2; if (btext[ind] != NULL) { if ((typ = rtptyp(btext[ind])) >= 0) AddSubMenu(new cRTplusList(typ)); } break; default: state = osContinue; } } static int ct; if (++ct >= 60) { ct = 0; Update(); } return state; } // --- cRTplusList ------------------------------------------------------ cRTplusList::cRTplusList(int Typ) :cOsdMenu(RTp_Titel, 4) { typ = Typ; refresh = false; Load(); Display(); } cRTplusList::~cRTplusList() { typ = 0; } void cRTplusList::Load(void) { char text[80]; struct tm *ts, tm_store; int ind, lfd = 0; ts = localtime_r(&rtp_content.start, &tm_store); switch (typ) { case 0: snprintf(text, sizeof(text), "-- %s (max. %d) --", tr("last seen Radiotext"), 2*MAX_RTPC); Add(new cOsdItem(hk(text))); snprintf(text, sizeof(text), "%s", " "); Add(new cOsdItem(hk(text))); ind = rtp_content.rt_Index; if (ind < (2*MAX_RTPC-1) && rtp_content.radiotext[ind+1] != NULL) { for (int i = ind+1; i < 2*MAX_RTPC; i++) { if (rtp_content.radiotext[i] != NULL) { snprintf(text, sizeof(text), "%d.\t%s", ++lfd, rtp_content.radiotext[i]); Add(new cOsdItem(hk(text))); } } } for (int i = 0; i <= ind; i++) { if (rtp_content.radiotext[i] != NULL) { snprintf(text, sizeof(text), "%d.\t%s", ++lfd, rtp_content.radiotext[i]); Add(new cOsdItem(hk(text)), refresh); } } break; case 1: SetCols(6, 19, 1); snprintf(text, sizeof(text), "-- %s --", tr("Playlist")); Add(new cOsdItem(hk(text))); snprintf(text, sizeof(text), "%s\t%s\t\t%s", tr("Time"), tr("Title"), tr("Artist")); Add(new cOsdItem(hk(text))); snprintf(text, sizeof(text), "%s", " "); Add(new cOsdItem(hk(text))); ind = rtp_content.item_Index; if (ind < (MAX_RTPC-1) && rtp_content.item_Title[ind+1] != NULL) { for (int i = ind+1; i < MAX_RTPC; i++) { if (rtp_content.item_Title[i] != NULL && rtp_content.item_Artist[i] != NULL) { ts = localtime_r(&rtp_content.item_Start[i], &tm_store); snprintf(text, sizeof(text), "%02d:%02d\t%s\t\t%s", ts->tm_hour, ts->tm_min, rtp_content.item_Title[i], rtp_content.item_Artist[i]); Add(new cOsdItem(hk(text))); } } } for (int i = 0; i <= ind; i++) { if (rtp_content.item_Title[i] != NULL && rtp_content.item_Artist[i] != NULL) { ts = localtime_r(&rtp_content.item_Start[i], &tm_store); snprintf(text, sizeof(text), "%02d:%02d\t%s\t\t%s", ts->tm_hour, ts->tm_min, rtp_content.item_Title[i], rtp_content.item_Artist[i]); Add(new cOsdItem(hk(text)), refresh); } } break; case 2: snprintf(text, sizeof(text), "-- %s --", tr("Sports")); Add(new cOsdItem(hk(text))); snprintf(text, sizeof(text), "%s", " "); Add(new cOsdItem(hk(text))); ind = rtp_content.info_SportIndex; if (ind < (MAX_RTPC-1) && rtp_content.info_Sport[ind+1] != NULL) { for (int i = ind+1; i < MAX_RTPC; i++) { if (rtp_content.info_Sport[i] != NULL) { snprintf(text, sizeof(text), "%d.\t%s", ++lfd, rtp_content.info_Sport[i]); Add(new cOsdItem(hk(text))); } } } for (int i = 0; i <= ind; i++) { if (rtp_content.info_Sport[i] != NULL) { snprintf(text, sizeof(text), "%d.\t%s", ++lfd, rtp_content.info_Sport[i]); Add(new cOsdItem(hk(text)), refresh); } } break; case 3: snprintf(text, sizeof(text), "-- %s --", tr("Lottery")); Add(new cOsdItem(hk(text))); snprintf(text, sizeof(text), "%s", " "); Add(new cOsdItem(hk(text))); ind = rtp_content.info_LotteryIndex; if (ind < (MAX_RTPC-1) && rtp_content.info_Lottery[ind+1] != NULL) { for (int i = ind+1; i < MAX_RTPC; i++) { if (rtp_content.info_Lottery[i] != NULL) { snprintf(text, sizeof(text), "%d.\t%s", ++lfd, rtp_content.info_Lottery[i]); Add(new cOsdItem(hk(text))); } } } for (int i = 0; i <= ind; i++) { if (rtp_content.info_Lottery[i] != NULL) { snprintf(text, sizeof(text), "%d.\t%s", ++lfd, rtp_content.info_Lottery[i]); Add(new cOsdItem(hk(text)), refresh); } } break; case 4: snprintf(text, sizeof(text), "-- %s --", tr("Weather")); Add(new cOsdItem(hk(text))); snprintf(text, sizeof(text), "%s", " "); Add(new cOsdItem(hk(text))); ind = rtp_content.info_WeatherIndex; if (ind < (MAX_RTPC-1) && rtp_content.info_Weather[ind+1] != NULL) { for (int i = ind+1; i < MAX_RTPC; i++) { if (rtp_content.info_Weather[i] != NULL) { snprintf(text, sizeof(text), "%d.\t%s", ++lfd, rtp_content.info_Weather[i]); Add(new cOsdItem(hk(text))); } } } for (int i = 0; i <= ind; i++) { if (rtp_content.info_Weather[i] != NULL) { snprintf(text, sizeof(text), "%d.\t%s", ++lfd, rtp_content.info_Weather[i]); Add(new cOsdItem(hk(text)), refresh); } } break; case 5: snprintf(text, sizeof(text), "-- %s --", tr("Stockmarket")); Add(new cOsdItem(hk(text))); snprintf(text, sizeof(text), "%s", " "); Add(new cOsdItem(hk(text))); ind = rtp_content.info_StockIndex; if (ind < (MAX_RTPC-1) && rtp_content.info_Stock[ind+1] != NULL) { for (int i = ind+1; i < MAX_RTPC; i++) { if (rtp_content.info_Stock[i] != NULL) { snprintf(text, sizeof(text), "%d.\t%s", ++lfd, rtp_content.info_Stock[i]); Add(new cOsdItem(hk(text))); } } } for (int i = 0; i <= ind; i++) { if (rtp_content.info_Stock[i] != NULL) { snprintf(text, sizeof(text), "%d.\t%s", ++lfd, rtp_content.info_Stock[i]); Add(new cOsdItem(hk(text)), refresh); } } break; case 6: snprintf(text, sizeof(text), "-- %s --", tr("Other")); Add(new cOsdItem(hk(text))); snprintf(text, sizeof(text), "%s", " "); Add(new cOsdItem(hk(text))); ind = rtp_content.info_OtherIndex; if (ind < (MAX_RTPC-1) && rtp_content.info_Other[ind+1] != NULL) { for (int i = ind+1; i < MAX_RTPC; i++) { if (rtp_content.info_Other[i] != NULL) { snprintf(text, sizeof(text), "%d.\t%s", ++lfd, rtp_content.info_Other[i]); Add(new cOsdItem(hk(text))); } } } for (int i = 0; i <= ind; i++) { if (rtp_content.info_Other[i] != NULL) { snprintf(text, sizeof(text), "%d.\t%s", ++lfd, rtp_content.info_Other[i]); Add(new cOsdItem(hk(text)), refresh); } } break; } SetHelp(NULL, NULL , refresh ? tr("Refresh Off") : tr("Refresh On"), tr("Back")); } void cRTplusList::Update(void) { Clear(); Load(); Display(); } eOSState cRTplusList::ProcessKey(eKeys Key) { eOSState state = cOsdMenu::ProcessKey(Key); if (state == osUnknown) { switch (Key) { case k0: Update(); break; case kYellow: refresh = (refresh) ? false : true; Update(); break; case kBack: case kOk: case kBlue: return osBack; default: state = osContinue; } } static int ct; if (refresh) { if (++ct >= 20) { ct = 0; Update(); } } return state; } //--------------- End ----------------------------------------------------------------- #endif CRadioText::CRadioText(void) { pid = 0; audioDemux = NULL; init(); running = true; start(); } CRadioText::~CRadioText(void) { printf("CRadioText::~CRadioText\n"); running = false; radiotext_stop(); cond.broadcast(); OpenThreads::Thread::join(); printf("CRadioText::~CRadioText done\n"); } void CRadioText::init() { S_Verbose = 0; S_RtFunc = 1; S_RtOsd = 0; S_RtOsdTitle = 1; S_RtOsdTags = 2; S_RtOsdPos = 2; S_RtOsdRows = 3; S_RtOsdLoop = 1; S_RtOsdTO = 60; S_RtSkinColor = false; S_RtBgCol = 0; S_RtBgTra = 0xA0; S_RtFgCol = 1; S_RtDispl = 1; S_RtMsgItems = 0; RT_Index = 0; RT_PTY = 0; // Radiotext RTP_ItemToggle = 1; RTP_TToggle = 0; RT_PlusShow = false; RT_Replay = false; RT_ReOpen = false; for (int i = 0; i < 5; i++) RT_Text[i][0] = 0; RDS_PTYN[0] = 0; #if ENABLE_RASS // Rass ... Rass_Show = -1; // -1=No, 0=Yes, 1=display Rass_Archiv = -1; // -1=Off, 0=Index, 1000-9990=Slidenr. #endif RT_MsgShow = false; // clear entries from old channel have_radiotext = false; } void CRadioText::radiotext_stop(void) { printf("CRadioText::radiotext_stop: ###################### pid 0x%x ######################\n", getPid()); if (getPid() != 0) { mutex.lock(); pid = 0; have_radiotext = false; S_RtOsd = 0; mutex.unlock(); } } void CRadioText::setPid(uint inPid) { printf("CRadioText::setPid: ###################### old pid 0x%x new pid 0x%x ######################\n", pid, inPid); if (pid != inPid) { mutex.lock(); pid = inPid; init(); mutex.unlock(); cond.broadcast(); } } void CRadioText::run() { uint current_pid = 0; printf("CRadioText::run: ###################### Starting thread ######################\n"); audioDemux = new cDemux(1); audioDemux->Open(DMX_PES_CHANNEL,0,128*1024); while(running) { mutex.lock(); if (pid == 0) { mutex.unlock(); audioDemux->Stop(); pidmutex.lock(); printf("CRadioText::run: ###################### waiting for pid.. ######################\n"); cond.wait(&pidmutex); pidmutex.unlock(); mutex.lock(); } if (pid && (current_pid != pid)) { current_pid = pid; printf("CRadioText::run: ###################### Setting PID 0x%x ######################\n", getPid()); audioDemux->Stop(); if (!audioDemux->pesFilter(getPid()) || !audioDemux->Start()) { pid = 0; printf("CRadioText::run: ###################### failed to start PES filter ######################\n"); } } mutex.unlock(); if (pid) { int n; unsigned char buf[0x1FFFF]; n = audioDemux->Read(buf, sizeof(buf), 500 /*5000*/); if (n > 0) { //printf("."); fflush(stdout); mutex.lock(); PES_Receive(buf, n); mutex.unlock(); } } } delete audioDemux; audioDemux = NULL; printf("CRadioText::run: ###################### exit ######################\n"); }