summaryrefslogtreecommitdiff
path: root/radio.c
diff options
context:
space:
mode:
authorUlrich Eckhardt <vdr@uli-eckhardt.de>2017-04-23 16:10:16 +0200
committerUlrich Eckhardt <vdr@uli-eckhardt.de>2017-04-23 16:10:16 +0200
commit1dbb7611337dc4b61817cad734a47b1a0404b77c (patch)
treee9b41e387c25c05678d84ce388f9e1977ff18f84 /radio.c
downloadvdr-plugin-radio-1dbb7611337dc4b61817cad734a47b1a0404b77c.tar.gz
vdr-plugin-radio-1dbb7611337dc4b61817cad734a47b1a0404b77c.tar.bz2
Import of original Radio Plugin 1.0.01.0.0
Diffstat (limited to 'radio.c')
-rw-r--r--radio.c731
1 files changed, 731 insertions, 0 deletions
diff --git a/radio.c b/radio.c
new file mode 100644
index 0000000..d01fa8b
--- /dev/null
+++ b/radio.c
@@ -0,0 +1,731 @@
+/*
+ * radio.c: A plugin for the Video Disk Recorder
+ *
+ * See the README file for copyright information and how to reach the author.
+ *
+ */
+
+#include <vdr/plugin.h>
+#include <vdr/status.h>
+#include <vdr/config.h>
+#include <vdr/interface.h>
+#include <vdr/transfer.h>
+#include "getopt.h"
+#include "radioaudio.h"
+#include "radiotools.h"
+#include "radioepg.h"
+#include "inforx.h"
+
+#if VDRVERSNUM < 10737
+ #error This version of radio-plugin requires vdr >= 1.7.37
+#endif
+
+static const char *VERSION = "1.0.0";
+static const char *DESCRIPTION = trNOOP("Radio Background-Image/RDS-Text");
+static const char *MAINMENUENTRY = trNOOP("Show RDS-Radiotext");
+char *ConfigDir;
+char *DataDir;
+char *LiveFile;
+char *ReplayFile;
+
+// Setup-Params
+int S_Activate = false;
+int S_StillPic = 1;
+int S_HMEntry = false;
+int S_RtFunc = 1;
+int S_RtOsdTitle = 1;
+int S_RtOsdTags = 2;
+int S_RtOsdPos = 1;
+int S_RtOsdRows = 2;
+int S_RtOsdLoop = 0;
+int S_RtOsdTO = 60;
+int S_RtSkinColor = 1;
+int S_RtBgCol = 0;
+int S_RtBgTra = 0xA0;
+int S_RtFgCol = 1;
+int S_RtDispl = 1;
+int S_RtMsgItems = 0;
+//int S_RtpMemNo = 25;
+int S_RassText = 1;
+int S_ExtInfo = 0;
+uint32_t rt_color[9];
+int S_Verbose = 1;
+int S_Encrypted = 0;
+// Radiotext
+char RT_Text[5][RT_MEL];
+char RTP_Artist[RT_MEL], RTP_Title[RT_MEL];
+int RT_Info, RT_Index, RT_PTY;
+time_t RTP_Starttime;
+bool RT_OsdTO = false, RTplus_Osd = false, RT_ReOpen = false;
+int RT_OsdTOTemp = 0, Radio_CA = 0;
+int RT_Charset = 0; // 0= ISO-8859-1, 1= UTF8, 2= ..
+// RadioCheck
+const cChannel *chan;
+int IsRadioOrReplay;
+// Info
+bool DoInfoReq = false, InfoRequest = false;
+int InfoTimeout = 3;
+
+struct RadioTextService_v1_0 {
+ int rds_info; // 0= no / 1= Text / 2= Text + RTplus-Tags (Item,Artist)
+ int rds_pty; // 0-31
+ char *rds_text;
+ char *rds_title;
+ char *rds_artist;
+ struct tm *title_start;
+};
+
+
+// --- cRadioCheck -------------------------------------------------------
+
+class cRadioCheck: public cThread {
+private:
+ static cRadioCheck *RadioCheck;
+protected:
+ virtual void Action(void);
+ void Stop(void);
+public:
+ cRadioCheck(void);
+ virtual ~cRadioCheck();
+ static void Init(void);
+ static void Exit(void);
+};
+
+cRadioCheck *cRadioCheck::RadioCheck = NULL;
+
+cRadioCheck::cRadioCheck(void)
+: cThread("radiocheck")
+{
+ IsRadioOrReplay = 0;
+}
+
+cRadioCheck::~cRadioCheck() {
+ if (Running())
+ Stop();
+}
+
+void cRadioCheck::Init(void) {
+ if (RadioCheck == NULL) {
+ RadioCheck = new cRadioCheck;
+ RadioCheck->Start();
+ }
+}
+
+void cRadioCheck::Exit(void) {
+ if (RadioCheck != NULL) {
+ RadioCheck->Stop();
+ DELETENULL(RadioCheck);
+ }
+}
+
+void cRadioCheck::Stop(void) {
+ Cancel(10);
+}
+
+void cRadioCheck::Action(void)
+{
+
+ if ((S_Verbose && 0x0f) >= 2)
+ printf("vdr-radio: background-checking starts\n");
+
+ while (Running()) {
+ cCondWait::SleepMs(2000);
+
+ // check Live-Radio
+ if (IsRadioOrReplay == 1 && chan != NULL) {
+ if (chan->Vpid()) {
+ isyslog("radio: channnel '%s' got Vpid= %d", chan->Name(), chan->Vpid());
+ IsRadioOrReplay = 0;
+ Channels.SwitchTo(cDevice::CurrentChannel());
+ //cDevice::PrimaryDevice()->SwitchChannel(chan, true);
+ }
+ else {
+ if ((InfoTimeout-=2) <= 0) {
+ InfoTimeout = 20;
+ int chtid = chan->Tid();
+ // Kanal-EPG PresentEvent
+ if (chan->Apid(0) > 0 && (chtid == PREMIERERADIO_TID || chtid == KDRADIO_TID
+ || chtid == UMRADIO_TID1 || chtid == UMRADIO_TID2 || chtid == UMRADIO_TID3 || chtid == UMRADIO_TID4 || chtid == UMRADIO_TID5)) {
+ cSchedulesLock schedLock;
+ const cSchedules *scheds = cSchedules::Schedules(schedLock);
+ if (scheds != NULL) {
+ const cSchedule *sched = scheds->GetSchedule(chan->GetChannelID());
+ if (sched != NULL) {
+ const cEvent *present = sched->GetPresentEvent();
+ if (present != NULL) {
+ if (chtid == PREMIERERADIO_TID) // Premiere
+ InfoTimeout = epg_premiere(present->Title(), present->Description(), present->StartTime(), present->EndTime());
+ else if (chtid == KDRADIO_TID) // Kabel Deutschland
+ InfoTimeout = epg_kdg(present->Description(), present->StartTime(), present->EndTime());
+ else // Unity Media Kabel
+ InfoTimeout = epg_unitymedia(present->Description(), present->StartTime(), present->EndTime());
+ InfoRequest = true;
+ }
+ else
+ dsyslog("radio: no event.present (Tid= %d, Apid= %d)", chtid, chan->Apid(0));
+ }
+ else
+ dsyslog("radio: no schedule (Tid= %d, Apid= %d)", chtid, chan->Apid(0));
+ }
+ }
+ // Artist/Title with external script?
+ else if (chan->Apid(0) > 0 && DoInfoReq) {
+ InfoTimeout = info_request(chtid, chan->Apid(0));
+ InfoRequest = (InfoTimeout > 0);
+ }
+ }
+ }
+ }
+
+ // temp. OSD-CloseTimeout
+ (RT_OsdTOTemp > 0) ? RT_OsdTOTemp -= 2 : RT_OsdTOTemp = 0; // in sec like this cycletime
+
+ // Radiotext-Autodisplay
+ if ((S_RtDispl == 2) && (RT_Info >= 0) && !RT_OsdTO && (RT_OsdTOTemp == 0) && RT_ReOpen && !Skins.IsOpen() && !cOsd::IsOpen())
+ cRemote::CallPlugin("radio");
+ }
+
+ if ((S_Verbose && 0x0f) >= 2)
+ printf("vdr-radio: background-checking ends\n");
+}
+
+
+// --- cMenuSetupRadio -------------------------------------------------------
+
+class cMenuSetupRadio : public cMenuSetupPage {
+private:
+ int newS_Activate;
+ int newS_StillPic;
+ int newS_HMEntry;
+ int newS_RtFunc;
+ int newS_RtOsdTitle;
+ int newS_RtOsdTags;
+ int newS_RtOsdPos;
+ int newS_RtOsdRows;
+ int newS_RtOsdLoop;
+ int newS_RtOsdTO;
+ int newS_RtSkinColor;
+ int newS_RtBgCol;
+ int newS_RtBgTra;
+ int newS_RtFgCol;
+ int newS_RtDispl;
+ int newS_RtMsgItems;
+ //int newS_RtpMemNo;
+ int newS_RassText;
+ int newS_ExtInfo;
+ const char *T_RtFunc[3];
+ const char *T_RtOsdTags[3];
+ const char *T_RtOsdPos[2];
+ const char *T_RtOsdLoop[2];
+ const char *T_RtBgColor[9];
+ const char *T_RtFgColor[9];
+ const char *T_RtDisplay[3];
+ const char *T_RtMsgItems[4];
+ const char *T_RassText[3];
+protected:
+ virtual void Store(void);
+public:
+ cMenuSetupRadio(void);
+};
+
+cMenuSetupRadio::cMenuSetupRadio(void)
+{
+ T_RtFunc[0] = tr("Off");
+ T_RtFunc[1] = tr("only Text");
+ T_RtFunc[2] = tr("Text+TagInfo");
+ T_RtOsdTags[0] = tr("Off");
+ T_RtOsdTags[1] = tr("only, if some");
+ T_RtOsdTags[2] = tr("always");
+ T_RtOsdPos[0] = tr("Top");
+ T_RtOsdPos[1] = tr("Bottom");
+ T_RtOsdLoop[0] = tr("latest at Top");
+ T_RtOsdLoop[1] = tr("latest at Bottom");
+ T_RtBgColor[0] = T_RtFgColor[0] = tr ("Black");
+ T_RtBgColor[1] = T_RtFgColor[1] = tr ("White");
+ T_RtBgColor[2] = T_RtFgColor[2] = tr ("Red");
+ T_RtBgColor[3] = T_RtFgColor[3] = tr ("Green");
+ T_RtBgColor[4] = T_RtFgColor[4] = tr ("Yellow");
+ T_RtBgColor[5] = T_RtFgColor[5] = tr ("Magenta");
+ T_RtBgColor[6] = T_RtFgColor[6] = tr ("Blue");
+ T_RtBgColor[7] = T_RtFgColor[7] = tr ("Cyan");
+ T_RtBgColor[8] = T_RtFgColor[8] = tr ("Transparent");
+ T_RtDisplay[0] = tr("Off");
+ T_RtDisplay[1] = tr("about MainMenu");
+ T_RtDisplay[2] = tr("Automatic");
+ T_RtMsgItems[0] = tr("Off");
+ T_RtMsgItems[1] = tr("only Taginfo");
+ T_RtMsgItems[2] = tr("only Text");
+ T_RtMsgItems[3] = tr("Text+TagInfo");
+ T_RassText[0] = tr("Off");
+ T_RassText[1] = tr("Rass only");
+ T_RassText[2] = tr("Rass+Text mixed");
+
+ newS_Activate = S_Activate;
+ newS_StillPic = S_StillPic;
+ newS_Activate = S_Activate;
+ newS_RtFunc = S_RtFunc;
+ newS_RtOsdTitle = S_RtOsdTitle;
+ newS_RtOsdTags = S_RtOsdTags;
+ newS_RtOsdPos = S_RtOsdPos;
+ newS_RtOsdRows = S_RtOsdRows;
+ newS_RtOsdLoop = S_RtOsdLoop;
+ newS_RtOsdTO = S_RtOsdTO;
+ newS_RtSkinColor = S_RtSkinColor;
+ newS_RtBgCol = S_RtBgCol;
+ newS_RtBgTra = S_RtBgTra;
+ newS_RtFgCol = S_RtFgCol;
+ newS_RtDispl = (S_RtDispl > 2 ? 2 : S_RtDispl);
+ newS_RtMsgItems = S_RtMsgItems;
+ //newS_RtpMemNo = S_RtpMemNo;
+ newS_RassText = S_RassText;
+ newS_ExtInfo = S_ExtInfo;
+
+ Add(new cMenuEditBoolItem( tr("Activate"), &newS_Activate));
+ Add(new cMenuEditBoolItem( tr("Use StillPicture-Function"), &newS_StillPic));
+ Add(new cMenuEditBoolItem( tr("Hide MainMenuEntry"), &newS_HMEntry));
+ Add(new cMenuEditStraItem( tr("RDSText Function"), &newS_RtFunc, 3, T_RtFunc));
+ Add(new cMenuEditStraItem( tr("RDSText OSD-Position"), &newS_RtOsdPos, 2, T_RtOsdPos));
+ Add(new cMenuEditBoolItem( tr("RDSText OSD-Titlerow"), &newS_RtOsdTitle));
+ Add(new cMenuEditIntItem( tr("RDSText OSD-Rows (1-5)"), &newS_RtOsdRows, 1, 5));
+ Add(new cMenuEditStraItem( tr("RDSText OSD-Scrollmode"), &newS_RtOsdLoop, 2, T_RtOsdLoop));
+ Add(new cMenuEditStraItem( tr("RDSText OSD-Taginfo"), &newS_RtOsdTags, 3, T_RtOsdTags));
+ Add(new cMenuEditBoolItem( tr("RDSText OSD-Skincolors used"), &newS_RtSkinColor));
+ if (newS_RtSkinColor == 0) {
+ Add(new cMenuEditStraItem( tr("RDSText OSD-Backgr.Color"), &newS_RtBgCol, 9, T_RtBgColor));
+ Add(new cMenuEditIntItem( tr("RDSText OSD-Backgr.Transp."), &newS_RtBgTra, 1, 255));
+ Add(new cMenuEditStraItem( tr("RDSText OSD-Foregr.Color"), &newS_RtFgCol, 8, T_RtFgColor));
+ }
+ Add(new cMenuEditIntItem( tr("RDSText OSD-Timeout (0-1440 min)"), &newS_RtOsdTO, 0, 1440));
+ Add(new cMenuEditStraItem( tr("RDSText OSD-Display"), &newS_RtDispl, 3, T_RtDisplay));
+ Add(new cMenuEditStraItem( tr("RDSText StatusMsg (lcdproc & co)"), &newS_RtMsgItems, 4, T_RtMsgItems));
+ //Add(new cMenuEditIntItem( tr("RDSplus Memorynumber (10-99)"), &newS_RtpMemNo, 10, 99));
+ Add(new cMenuEditStraItem( tr("RDSText Rass-Function"), &newS_RassText, 3, T_RassText));
+ Add(new cMenuEditBoolItem( tr("External Info-Request"), &newS_ExtInfo));
+}
+
+void cMenuSetupRadio::Store(void)
+{
+ SetupStore("Activate", S_Activate = newS_Activate);
+ SetupStore("UseStillPic", S_StillPic = newS_StillPic);
+ SetupStore("HideMenuEntry", S_HMEntry = newS_HMEntry);
+ SetupStore("RDSText-Function", S_RtFunc = newS_RtFunc);
+ SetupStore("RDSText-OsdTitle", S_RtOsdTitle = newS_RtOsdTitle);
+ SetupStore("RDSText-OsdTags", S_RtOsdTags = newS_RtOsdTags);
+ SetupStore("RDSText-OsdPosition", S_RtOsdPos = newS_RtOsdPos);
+ SetupStore("RDSText-OsdRows", S_RtOsdRows = newS_RtOsdRows);
+ SetupStore("RDSText-OsdLooping", S_RtOsdLoop = newS_RtOsdLoop);
+ SetupStore("RDSText-OsdSkinColor", S_RtSkinColor = newS_RtSkinColor);
+ SetupStore("RDSText-OsdBackgrColor", S_RtBgCol = newS_RtBgCol);
+ SetupStore("RDSText-OsdBackgrTrans", S_RtBgTra = newS_RtBgTra);
+ SetupStore("RDSText-OsdForegrColor", S_RtFgCol = newS_RtFgCol);
+ SetupStore("RDSText-OsdTimeout", S_RtOsdTO = newS_RtOsdTO);
+ SetupStore("RDSText-Display", S_RtDispl = newS_RtDispl);
+ SetupStore("RDSText-MsgItems", S_RtMsgItems = newS_RtMsgItems);
+ //SetupStore("RDSplus-MemNumber", S_RtpMemNo = newS_RtpMemNo);
+ SetupStore("RDSText-Rass", S_RassText = newS_RassText);
+ SetupStore("ExtInfo-Req", S_ExtInfo = newS_ExtInfo);
+}
+
+
+// --- cPluginRadio -------------------------------------------------------
+
+
+class cRadioImage;
+class cRadioAudio;
+
+class cPluginRadio : public cPlugin, cStatus {
+private:
+ // Add any member variables or functions you may need here.
+ bool ConfigDirParam;
+ bool DataDirParam;
+ bool LiveFileParam;
+ bool ReplayFileParam;
+ cRadioImage *radioImage;
+ cRadioAudio *radioAudio;
+public:
+ cPluginRadio(void);
+ virtual ~cPluginRadio();
+ virtual const char *Version(void) { return VERSION; }
+ virtual const char *Description(void) { return tr(DESCRIPTION); }
+ virtual const char *CommandLineHelp(void);
+ virtual bool ProcessArgs(int argc, char *argv[]);
+ virtual bool Start(void);
+ virtual void Stop(void);
+ virtual void Housekeeping(void);
+ virtual void MainThreadHook(void) { }
+ virtual cString Active(void) { return NULL; }
+ virtual const char *MainMenuEntry(void) { return (S_Activate==0 || S_RtFunc==0 || S_RtDispl==0 || S_HMEntry ? NULL : tr(MAINMENUENTRY)); }
+ virtual cOsdObject *MainMenuAction(void);
+ virtual cMenuSetupPage *SetupMenu(void);
+ virtual bool SetupParse(const char *Name, const char *Value);
+ virtual bool Service(const char *Id, void *Data);
+ virtual const char **SVDRPHelpPages(void);
+ virtual cString SVDRPCommand(const char *Command, const char *Option, int &ReplyCode);
+protected:
+ virtual void ChannelSwitch(const cDevice *Device, int ChannelNumber, bool LiveView);
+ virtual void Replaying(const cControl *Control, const char *Name, const char *FileName, bool On);
+};
+
+cPluginRadio::cPluginRadio(void)
+{
+ // Initialize any member variables here.
+ // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
+ // VDR OBJECTS TO EXIST OR PROADUCE ANY OUTPUT!
+
+ radioImage = 0;
+ radioAudio = 0;
+
+ ConfigDirParam = false;
+ DataDirParam = false;
+ LiveFileParam = false;
+ ReplayFileParam = false;
+
+ rt_color[0] = 0xFF000000; //Black
+ rt_color[1] = 0xFFFCFCFC; //White
+ rt_color[2] = 0xFFFC1414; //Red
+ rt_color[3] = 0xFF24FC24; //Green
+ rt_color[4] = 0xFFFCC024; //Yellow
+ rt_color[5] = 0xFFB000FC; //Magenta
+ rt_color[6] = 0xFF0000FC; //Blue
+ rt_color[7] = 0xFF00FCFC; //Cyan
+ rt_color[8] = 0x00000000; //Transparent
+}
+
+cPluginRadio::~cPluginRadio()
+{
+ // Clean up after yourself!
+ if (ConfigDir) free(ConfigDir);
+ if (DataDir) free(DataDir);
+ if (LiveFile) free(LiveFile);
+ if (ReplayFile) free(ReplayFile);
+
+ cRadioCheck::Exit();
+ radioImage->Exit();
+}
+
+
+const char *cPluginRadio::CommandLineHelp(void)
+{
+ // Return a string that describes all known command line options.
+ return " -f dir, --files=dir use dir as image directory (default: <vdrconfig>/plugins/radio)\n"
+ " -d dir, --data=dir use dir as temp. data directory (default: <vdrconfig>/plugins/radio)\n"
+ " -l file, --live=file use file as default mpegfile in livemode (default: <dir>/radio.mpg)\n"
+ " -r file, --replay=file use file as default mpegfile in replaymode (default: <dir>/replay.mpg)\n"
+ " -e 1, --encrypted=1 use transfermode/backgroundimage @ encrypted radiochannels \n"
+ " -v level, --verbose=level set verbose level (default = 1, 0 = Off, 1 = RDS-Text+Tags, \n"
+ " 2 = +RDS-Telegram/Debug, 3 = +RawData 0xfd, \n"
+ " += 16 = Rass-Info, +=32 = TMC-Info) \n";
+}
+
+bool cPluginRadio::ProcessArgs(int argc, char *argv[])
+{
+ // Implement command line argument processing here if applicable.
+
+ static struct option long_options[] = {
+ { "files", required_argument, NULL, 'f' },
+ { "data", required_argument, NULL, 'd' },
+ { "live", required_argument, NULL, 'l' },
+ { "replay", required_argument, NULL, 'r' },
+ { "encrypted", required_argument, NULL, 'e' },
+ { "verbose", required_argument, NULL, 'v' },
+ { NULL }
+ };
+
+ int c;
+ while ((c = getopt_long(argc, argv, "f:d:l:r:e:v:", long_options, NULL)) != -1) {
+ switch (c) {
+ case 'f':
+ printf("vdr-radio: arg files-dir = %s\n", optarg);
+ ConfigDir = strdup(optarg);
+ ConfigDirParam = true;
+ break;
+ case 'd':
+ printf("vdr-radio: arg data-dir = %s\n", optarg);
+ DataDir = strdup(optarg);
+ DataDirParam = true;
+ break;
+ case 'l':
+ printf("vdr-radio: arg live-mpeg = %s\n", optarg);
+ LiveFile = strdup(optarg);
+ LiveFileParam = true;
+ break;
+ case 'r':
+ printf("vdr-radio: arg replay-mpeg = %s\n", optarg);
+ ReplayFile = strdup(optarg);
+ ReplayFileParam = true;
+ break;
+ case 'v':
+ printf("vdr-radio: arg verbose = %s\n", optarg);
+ if (isnumber(optarg))
+ S_Verbose = atoi(optarg);
+ break;
+ case 'e':
+ printf("vdr-radio: arg encrypted = %s\n", optarg);
+ if (isnumber(optarg))
+ S_Encrypted = atoi(optarg);
+ break;
+ default:
+ printf("vdr-radio: arg char = %c\n", c);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool cPluginRadio::Start(void)
+{
+ // Start any background activities the plugin shall perform.
+ printf("vdr-radio: Radio-Plugin Backgr.Image/RDS-Text starts...\n");
+
+ radioImage = new cRadioImage;
+ if (!radioImage)
+ return false;
+ radioImage->Init();
+
+ radioAudio = new cRadioAudio;
+ if (!radioAudio)
+ return false;
+
+ if (!ConfigDirParam)
+ ConfigDir = strdup(ConfigDirectory(Name()));
+ if (!DataDirParam) {
+ DataDir = strdup("/tmp/vdr-radio.XXXXXX");
+ mkdtemp(DataDir);
+ }
+ if (!LiveFileParam)
+ asprintf(&LiveFile, "%s/radio.mpg", ConfigDir);
+ if (!ReplayFileParam)
+ asprintf(&ReplayFile, "%s/replay.mpg", ConfigDir);
+
+ cRadioCheck::Init();
+
+ return true;
+}
+
+void cPluginRadio::Stop(void)
+{
+ cRadioCheck::Exit();
+
+ if (IsRadioOrReplay > 0)
+ radioAudio->DisableRadioTextProcessing();
+
+ radioImage->Exit();
+}
+
+void cPluginRadio::Housekeeping(void)
+{
+ // Perform any cleanup or other regular tasks.
+}
+
+cOsdObject *cPluginRadio::MainMenuAction(void)
+{
+ // Perform the action when selected from the main VDR menu.
+/* if (!cDevice::PrimaryDevice()->Transferring() && !cDevice::PrimaryDevice()->Replaying()) {
+ //cRemote::CallPlugin("radio"); // try again later <-- disabled, looping if activate over menu @ tv in dvb-livemode
+ } */
+ if (S_Activate > 0 && S_RtFunc > 0 && S_RtDispl > 0 && IsRadioOrReplay > 0) {
+ if (!RTplus_Osd) {
+ cRadioTextOsd *rtosd = new cRadioTextOsd();
+ return rtosd;
+ }
+ else {
+ cRTplusOsd *rtposd = new cRTplusOsd();
+ return rtposd;
+ }
+ }
+
+ return NULL;
+}
+
+cMenuSetupPage *cPluginRadio::SetupMenu(void)
+{
+ // Return a setup menu in case the plugin supports one.
+ return new cMenuSetupRadio;
+}
+
+bool cPluginRadio::SetupParse(const char *Name, const char *Value)
+{
+ // Parse your own setup parameters and store their values.
+ if (!strcasecmp(Name, "Activate")) S_Activate = atoi(Value);
+ else if (!strcasecmp(Name, "UseStillPic")) S_StillPic = atoi(Value);
+ else if (!strcasecmp(Name, "HideMenuEntry")) S_HMEntry = atoi(Value);
+ else if (!strcasecmp(Name, "RDSText-Function")) S_RtFunc = atoi(Value);
+ else if (!strcasecmp(Name, "RDSText-OsdTitle")) S_RtOsdTitle = atoi(Value);
+ else if (!strcasecmp(Name, "RDSText-OsdTags")) S_RtOsdTags = atoi(Value);
+ else if (!strcasecmp(Name, "RDSText-OsdPosition")) S_RtOsdPos = atoi(Value);
+ else if (!strcasecmp(Name, "RDSText-OsdRows")) {
+ S_RtOsdRows = atoi(Value);
+ if (S_RtOsdRows > 5) S_RtOsdRows = 5;
+ }
+ else if (!strcasecmp(Name, "RDSText-OsdLooping")) S_RtOsdLoop = atoi(Value);
+ else if (!strcasecmp(Name, "RDSText-OsdSkinColor")) S_RtSkinColor = atoi(Value);
+ else if (!strcasecmp(Name, "RDSText-OsdBackgrColor")) S_RtBgCol = atoi(Value);
+ else if (!strcasecmp(Name, "RDSText-OsdBackgrTrans")) S_RtBgTra = atoi(Value);
+ else if (!strcasecmp(Name, "RDSText-OsdForegrColor")) S_RtFgCol = atoi(Value);
+ else if (!strcasecmp(Name, "RDSText-OsdTimeout")) {
+ S_RtOsdTO = atoi(Value);
+ if (S_RtOsdTO > 1440) S_RtOsdTO = 1440;
+ }
+ else if (!strcasecmp(Name, "RDSText-Display")) S_RtDispl = atoi(Value);
+ else if (!strcasecmp(Name, "RDSText-MsgItems")) S_RtMsgItems = atoi(Value);
+ //else if (!strcasecmp(Name, "RDSplus-MemNumber")) S_RtpMemNo = atoi(Value);
+ else if (!strcasecmp(Name, "RDSText-Rass")) S_RassText = atoi(Value);
+ else if (!strcasecmp(Name, "ExtInfo-Req")) S_ExtInfo = atoi(Value);
+ else
+ return false;
+
+ return true;
+}
+
+bool cPluginRadio::Service(const char *Id, void *Data)
+{
+ if (strcmp(Id,"RadioTextService-v1.0") == 0 && S_Activate > 0 && S_RtFunc >= 1) {
+ if (Data) {
+ RadioTextService_v1_0 *data = (RadioTextService_v1_0*)Data;
+ data->rds_pty = RT_PTY;
+ data->rds_info = (RT_Info < 0) ? 0 : RT_Info;
+ int ind = (RT_Index == 0) ? S_RtOsdRows - 1 : RT_Index - 1;
+ data->rds_text = RT_Text[ind];
+ data->rds_title = RTP_Title;
+ data->rds_artist = RTP_Artist;
+ struct tm tm_store;
+ data->title_start = localtime_r(&RTP_Starttime, &tm_store);
+ }
+ return true;
+ }
+
+ return false;
+}
+
+const char **cPluginRadio::SVDRPHelpPages(void)
+{
+ static const char *HelpPages[] = {
+ "RTINFO\n"
+ " Print the radiotext information.",
+ "RTCLOSE\n"
+ " Close the radiotext-osd,\n"
+ " Reopen can only be done over menu or channelswitch.",
+ "RTTCLOSE\n"
+ " Close the radiotext-osd temporarily,\n"
+ " Reopen will be done after osd-messagetimeout.",
+ NULL
+ };
+
+ return HelpPages;
+}
+
+cString cPluginRadio::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode)
+{
+ if (strcasecmp(Command, "RTINFO") == 0) {
+ // we use the default reply code here
+ if (RT_Info == 2) {
+ int ind = (RT_Index == 0) ? S_RtOsdRows - 1 : RT_Index - 1;
+ return cString::sprintf(" Radiotext: %s\n RT-Title : %s\n RT-Artist: %s\n", RT_Text[ind], RTP_Title, RTP_Artist);
+ }
+ else if (RT_Info == 1) {
+ int ind = (RT_Index == 0) ? S_RtOsdRows - 1 : RT_Index - 1;
+ return cString::sprintf(" Radiotext: %s\n", RT_Text[ind]);
+ }
+ else
+ return cString::sprintf(" Radiotext not available (yet)\n");
+ }
+ else if (strcasecmp(Command, "RTCLOSE") == 0) {
+ // we use the default reply code here
+ if (RT_OsdTO)
+ return cString::sprintf("RT-OSD already closed");
+ else {
+ RT_OsdTO = true;
+ return cString::sprintf("RT-OSD will be closed now");
+ }
+ }
+ else if (strcasecmp(Command, "RTTCLOSE") == 0) {
+ // we use the default reply code here
+ RT_OsdTOTemp = 2 * Setup.OSDMessageTime;
+ return cString::sprintf("RT-OSD will be temporarily closed");
+ }
+
+ return NULL;
+}
+
+void cPluginRadio::ChannelSwitch(const cDevice *Device, int ChannelNumber, bool LiveView)
+{
+ if (Device != cDevice::PrimaryDevice()) return;
+
+ IsRadioOrReplay = Radio_CA = 0;
+ radioAudio->DisableRadioTextProcessing();
+ InfoTimeout = 3;
+
+ if (S_Activate == false) return;
+
+ char *image;
+ if (cDevice::CurrentChannel() == ChannelNumber) {
+ chan = ChannelNumber ? Channels.GetByNumber(ChannelNumber) : NULL;
+ if (chan != NULL && chan->Vpid() == 0 && chan->Apid(0) > 0) {
+ asprintf(&image, "%s/%s.mpg", ConfigDir, chan->Name());
+ if (!file_exists(image)) {
+ dsyslog("radio: channel-image not found '%s' (Channelname= %s)", image, chan->Name());
+ free(image);
+ asprintf(&image, "%s", LiveFile);
+ if (!file_exists(image))
+ dsyslog("radio: live-image not found '%s' (Channelname= %s)", image, chan->Name());
+ }
+ dsyslog("radio: [ChannelSwitch # Apid= %d, Ca= %d] channelname '%s', use image '%s'", chan->Apid(0), chan->Ca(0), chan->Name(), image);
+ if ((Radio_CA = chan->Ca(0)) == 0 || S_Encrypted == 1)
+ cDevice::PrimaryDevice()->ForceTransferMode();
+ radioImage->SetBackgroundImage(image);
+ radioAudio->EnableRadioTextProcessing(chan->Name(), chan->Apid(0), false);
+ free(image);
+ IsRadioOrReplay = 1;
+ DoInfoReq = (S_ExtInfo > 0);
+ }
+ }
+}
+
+void cPluginRadio::Replaying(const cControl *Control, const char *Name, const char *FileName, bool On)
+{
+ IsRadioOrReplay = 0;
+ radioAudio->DisableRadioTextProcessing();
+
+ if (S_Activate == false) return;
+
+ bool isRadio = false;
+
+ if (On && FileName != NULL) {
+ char *vdrfile;
+ // check VDR PES-Recordings
+ asprintf(&vdrfile, "%s/001.vdr", FileName);
+ if (file_exists(vdrfile)) {
+ cFileName fn(FileName, false, true, true);
+ cUnbufferedFile *f = fn.Open();
+ if (f) {
+ uchar b[4] = { 0x00, 0x00, 0x00, 0x00 };
+ ReadFrame(f, b, sizeof (b), sizeof (b));
+ fn.Close();
+ isRadio = (b[0] == 0x00) && (b[1] == 0x00) && (b[2] == 0x01) && (0xc0 <= b[3] && b[3] <= 0xdf);
+ }
+ }
+ // check VDR TS-Recordings
+ asprintf(&vdrfile, "%s/info", FileName);
+ if (file_exists(vdrfile)) {
+ cRecordingInfo rfi(FileName);
+ if (rfi.Read()) {
+ if (rfi.FramesPerSecond() > 0 && rfi.FramesPerSecond() < 18) // max. seen 13.88 @ ARD-RadioTP 320k
+ isRadio = true;
+ }
+ }
+ free(vdrfile);
+ }
+
+ if (isRadio) {
+ if (!file_exists(ReplayFile))
+ dsyslog("radio: replay-image not found '%s'", ReplayFile);
+ else
+ radioImage->SetBackgroundImage(ReplayFile);
+ radioAudio->EnableRadioTextProcessing(Name, 0, true);
+ IsRadioOrReplay = 2;
+ }
+}
+
+
+VDRPLUGINCREATOR(cPluginRadio); // Don't touch this!