/* * advchctrl.c: A plugin for the Video Disk Recorder * * See the README file for copyright information and how to reach the author. * * $Id$ */ //#include //#include //#include //#include //#include //#include //#include //#include //#include //#include //#include //#include "channels.h" //#include "config.h" //#include "cutter.h" //#include "device.h" //#include "eitscan.h" //#include "keys.h" //#include "menu.h" //#include "plugin.h" //#include "remote.h" //#include "timers.h" //#include "tools.h" //#include "videodir.h" #include #include #include #include "advchctrlconfig.h" #include "advchctrl.h" #include "advchctrlchannel.h" #include "advchctrlsetup.h" #include "advchctrlosd.h" #include "advchctrlcommon.h" #include "advchctrli18n.h" //***** The cStatus Interface Class Implementation **************************************************************************** //extern cAdvChCtrlChannels AdvChCtrlChannelsList; void cStatusAdvChCtrl::ChannelSwitch (const cDevice *Device, int ChannelNumber, bool LiveView) { isInReplayMode = Device->PrimaryDevice()->Replaying(); // ok in Transfermode we don't want to change the Volume isMute = Device->PrimaryDevice()->IsMute(); DEBUGVOL ("cStatusAdvChCtrl::Channelswitch Device <%d> Channel <%d>,isPrimaryDevice <%s>,isReplaying <%s>, isMuted<%s> ", Device->CardIndex(), ChannelNumber, Device->IsPrimaryDevice() ? "yes": "no", Device->Replaying() ? "yes": "no", Device->IsMute() ? "yes":"no"); // find the actual current channel cChannel *Channel = Channels.GetByNumber(Device->PrimaryDevice()->CurrentChannel()); if (Channel && !(ChannelNumber == 0) && Device->IsPrimaryDevice()) //&& !(isMute)) { tChannelID mycurrent = Channel->GetChannelID(); cDevice *myDevice = Device->PrimaryDevice(); int ChVolume = AdvChCtrlChannelsList.GetVolume(mycurrent); DEBUGVOL ("cStatusAdvChCtrl::Channelswitch Channel-ID <%s> ChVolume <%d>" , *(mycurrent.ToString()), ChVolume ); if (ChVolume > 0) { if (!isInReplayMode) { myDevice->SetVolume(ChVolume, 1); if (isMute) { myDevice->ToggleMute(); } DEBUGVOL ("cStatusAdvChCtrl::Channelswitch SetVolume" ); } ActualVolume = ChVolume; } if (ChVolume < 0) { if (!isInReplayMode) { myDevice->SetVolume(advchctrlConfig.defaultvolume, 1); DEBUGVOL ("cStatusAdvChCtrl::Channelswitch SetDefaultVolume" ); if (isMute) { myDevice->ToggleMute(); } } ActualVolume = advchctrlConfig.defaultvolume; } } } void cStatusAdvChCtrl::SetVolume (int Volume, bool Absolute) { // DEBUGVOL ("cStatusAdvChCtrl::SetVolume <%d> <%d>", Volume, Absolute); // here we need the current channel of the primary device cDevice *PrimaryDev = cDevice::PrimaryDevice(); if (PrimaryDev) { cChannel *Channel = Channels.GetByNumber(PrimaryDev->CurrentChannel()); if (Channel) { // now we get the unique ChannelID tChannelID mycurrent = Channel->GetChannelID(); // we call the channel class for the actual channel volume, but not when in Replaymode if (!isInReplayMode) { int ChVolume = AdvChCtrlChannelsList.GetVolume(mycurrent); if (!PrimaryDev->IsMute()) { int SetVolume = isMute ? ChVolume : Volume; AdvChCtrlChannelsList.AddAVolCtrlChannel(mycurrent, SetVolume, advchctrlConfig.defaultvolume); if (isMute) { isMute = false; PrimaryDev->SetVolume(SetVolume, 1); DEBUGVOL ("cStatusAdvChCtrl::SetVolume Channel-ID <%s>, <%d>" , *(mycurrent.ToString()),SetVolume); } } else { // DEBUGVOL ("cStatusAdvChCtrl::SetVolume Channel-ID <%s>, <%d> isMute" , *(mycurrent.ToString()),ChVolume); // cDevice::PrimaryDevice()->SetVolume(ChVolume, 1); isMute = true; } } } } } #if VDRVERSNUM >= 10338 void cStatusAdvChCtrl::Replaying(const cControl *Control, const char *Name, const char *FileName, bool On) { isInReplayMode = On; #else void cStatusAdvChCtrl::Replaying(const cControl *Control, const char *Name) { isInReplayMode = (Name != NULL ? true : false); #endif DEBUGVOL ("cStatusAdvChCtrl::Replaying <%s> <%s>", Name, (isInReplayMode ? "yes" : "no")); if (!(ActualVolume == advchctrlConfig.defaultvolume) && isInReplayMode) { cDevice *myPrimary = cDevice::PrimaryDevice(); // Reset Volume to Default volume on start of replay myPrimary->SetVolume(advchctrlConfig.defaultvolume, 1); //cDevice::PrimaryDevice()->SetVolume(advchctrlConfig.defaultvolume, 1); DEBUGVOL ("cStatusAdvChCtrl::Channelswitch SetDefaultVolume on Replaystart" ); ActualVolume = advchctrlConfig.defaultvolume; } } //***** The cPlugin Interface Class Implementation ************************************************************** cPluginAdvChCtrl::cPluginAdvChCtrl(void) { // Initialize any member variables here. // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT! statusAdvChCtrl = NULL; advchctrlConfig.defaultvolume = 100; advchctrlConfig.hidemainmenu = 1; advchctrlConfig.osdposition = 0; advchctrlConfig.osdwidth = 600; advchctrlConfig.osdheight = 400; advchctrlConfig.osdoffset = 0; advchctrlConfig.theme = eThemeClassic; } cPluginAdvChCtrl::~cPluginAdvChCtrl() { // Cleanup after yourself! delete statusAdvChCtrl; } const char *cPluginAdvChCtrl::CommandLineHelp(void) { // Return a string that describes all known command line options. return NULL; } bool cPluginAdvChCtrl::ProcessArgs(int argc, char *argv[]) { // Implement command line argument processing here if applicable. return true; } bool cPluginAdvChCtrl::Initialize(void) { // Initialize any background activities the plugin shall perform. // we want support other languages return true; } bool cPluginAdvChCtrl::Start(void) { // Start any background activities the plugin shall perform. statusAdvChCtrl = new cStatusAdvChCtrl; if (!AdvChCtrlChannelsList.Load(AddDirectory(ConfigDirectory(),"AdvChCtrl.conf"))) { isyslog ("AdvChCtrl: Loading 'AdvChCtrl.conf' faild"); } AdvChCtrlChannelsList.Save(); return true; } void cPluginAdvChCtrl::Stop(void) { // Stop any background activities the plugin shall perform. } void cPluginAdvChCtrl::Housekeeping(void) { // Perform any cleanup or other regular tasks. } cOsdObject *cPluginAdvChCtrl::MainMenuAction(void) { // Perform the action when selected from the main VDR menu. return new cAdvChCtrlOsd; } cMenuSetupPage *cPluginAdvChCtrl::SetupMenu(void) { // Return a setup menu in case the plugin supports one. return new cAdvChCtrlSetup; } bool cPluginAdvChCtrl::SetupParse(const char *Name, const char *Value) { // Parse your own setup parameters and store their values. if (!strcasecmp(Name, "DefaultVolume")) advchctrlConfig.defaultvolume = atoi(Value); else if (!strcasecmp (Name, "HideMainMenu")) advchctrlConfig.hidemainmenu = atoi(Value); else if (!strcasecmp(Name, "OSDPosition")) advchctrlConfig.osdposition = atoi(Value); else if (!strcasecmp(Name, "OSDHeight")) advchctrlConfig.osdheight = atoi(Value); else if (!strcasecmp(Name, "OSDWidth")) advchctrlConfig.osdwidth = atoi(Value); else if (!strcasecmp(Name, "OSDOffset")) advchctrlConfig.osdoffset = atoi(Value); else if (!strcasecmp(Name, "Theme")) advchctrlConfig.theme = atoi(Value); // else if (!strcasecmp(Name, "RedLimit")) advchctrlConfig.redlimit = atoi(Value); // else if (!strcasecmp(Name, "GreenLimit")) advchctrlConfig.greenlimit = atoi(Value); // else if (!strcasecmp(Name, "UpdateInterval")) advchctrlConfig.updateinterval = atoi(Value); else return false; if (advchctrlConfig.theme < 0 || advchctrlConfig.theme >= eThemeMaxNumber) advchctrlConfig.theme = eThemeClassic; return true; } bool cPluginAdvChCtrl::Service(const char *Id, void *Data) { // Handle custom service requests from other plugins return false; } const char **cPluginAdvChCtrl::SVDRPHelpPages(void) { static const char *HelpPages[] = { "PVOLU []\n" " Prints out channel volume for ,\n" " and default channel volume, when called without parameter.\n", "RVOLU []\n" " Resets the channel volume to the default channel volume \n" " for . channel can be a valid channel number, \n" " or 0 to reset the actual channel volume.\n", "SVOLU ,\n" " Set the default channel volume to .\n" " range vor from 0 to 255\n", NULL }; return HelpPages; } cString cPluginAdvChCtrl::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode) { if (strcasecmp(Command, "PVOLU") == 0) return SVDRPCmdPvolu(Option, ReplyCode); if (strcasecmp(Command, "RVOLU") == 0) return SVDRPCmdRvolu(Option, ReplyCode); if (strcasecmp(Command, "SVOLU") == 0) return SVDRPCmdSvolu(Option, ReplyCode); ReplyCode = 500; return cString::sprintf("Unknown command: \"%s\"", Command); } cString cPluginAdvChCtrl::SVDRPCmdPvolu(const char *Option, int &ReplyCode) { ReplyCode = 900; if (*Option) { cChannel *Channel = NULL; if (isnumber(Option)) { int myChannelNr = strtol(Option, NULL, 10); Channel = Channels.GetByNumber((0 == myChannelNr) ? cDevice::PrimaryDevice()->CurrentChannel(): myChannelNr); } //DEBUGSVDRP("Option:<%s> myChannelNr=%d\n", Option, myChannelNr); if (Channel) { tChannelID myCurrentID = Channel->GetChannelID(); int ChVolume = AdvChCtrlChannelsList.GetVolume(myCurrentID); DEBUGSVDRP ("cStatusAdvChCtrl::SVDRPCmdPvolu Channel-ID <%s> ChVolume <%d>" , *(myCurrentID.ToString()), ChVolume ); if (ChVolume < 0) { ReplyCode = 901; return cString::sprintf("%d ;%s\n", advchctrlConfig.defaultvolume, "Channel has default volume"); } return cString::sprintf("%d \n", ChVolume ); } ReplyCode = 502; return cString::sprintf ("Unknown channel number <%s>\n", Option); } ReplyCode = 901; return cString::sprintf("%d ;%s\n", advchctrlConfig.defaultvolume, "this is the default channel volume"); } cString cPluginAdvChCtrl::SVDRPCmdRvolu(const char *Option, int &ReplyCode) { ReplyCode = 900; if (*Option) { cChannel *Channel = NULL; if (isnumber(Option)) { int myChannelNr = strtol(Option, NULL, 10); Channel = Channels.GetByNumber((0 == myChannelNr) ? cDevice::PrimaryDevice()->CurrentChannel(): myChannelNr); } else Channel = Channels.GetByChannelID(tChannelID::FromString(Option)); // DEBUGSVDRP("Option:<%s> myChannelNr=%d\n", Option, myChannelNr); if (Channel) { tChannelID myCurrentID = Channel->GetChannelID(); AdvChCtrlChannelsList.AddAVolCtrlChannel(myCurrentID, advchctrlConfig.defaultvolume, advchctrlConfig.defaultvolume); //AdvChCtrlChannelsList.Save(); if (! cDevice::PrimaryDevice()->Replaying()) { bool isMute = cDevice::PrimaryDevice()->IsMute(); cDevice::PrimaryDevice()->SetVolume(advchctrlConfig.defaultvolume,1); if (isMute) cDevice::PrimaryDevice()->ToggleMute(); } DEBUGSVDRP ("cStatusAdvChCtrl::SVDRPCmdPvolu Channel-ID <%s> reset to default volume" , *(myCurrentID.ToString())); ReplyCode = 901; return cString::sprintf("%d ;%s\n", advchctrlConfig.defaultvolume, "Channel is reset to default volume"); } ReplyCode = 502; return cString::sprintf ("Unknown channel number <%s>\n", Option); //return cString::sprintf("%ld\nThis is the number of seconds since the epoch\nand a demo of a multi-line reply", time(NULL)); } ReplyCode = 502; return cString::sprintf("RVOLU Not yet implemented \n"); } cString cPluginAdvChCtrl::SVDRPCmdSvolu(const char *Option, int &ReplyCode) { ReplyCode = 900; if (*Option) { //return cString::sprintf("%ld\nThis is the number of seconds since the epoch\nand a demo of a multi-line reply", time(NULL)); char *strChannel = NULL; char buf[strlen(Option) + 1]; char *p = strcpy(buf, Option); const char *delim = " \t"; char *strtok_next; strChannel = strtok_r(p, delim, &strtok_next); DEBUGSVDRP ("cStatusAdvChCtrl::SVDRPCmdSvolu Channel-ID <%s> isnumber():%s" , strChannel,(isnumber(strChannel)? "yes":"no")); cChannel *Channel = NULL; if (isnumber(strChannel)) { int myChannelNr = strtol(strChannel, NULL, 10); if (myChannelNr < 0) { ReplyCode = 501; return cString::sprintf("Illegal channel \"%d\"", myChannelNr); } Channel = Channels.GetByNumber((0 == myChannelNr) ? cDevice::PrimaryDevice()->CurrentChannel(): myChannelNr); if (Channel) { if ((p = strtok_r(NULL, delim, &strtok_next)) != NULL) { if (isnumber(p)){ int ChVolume = atoi(p); if (ChVolume >= 0 && ChVolume < 256) { DEBUGSVDRP ("cStatusAdvChCtrl::SVDRPCmdSvolu Channel-ID <%s> <%d>" , strChannel, ChVolume); AdvChCtrlChannelsList.AddAVolCtrlChannel(Channel->GetChannelID(), ChVolume, advchctrlConfig.defaultvolume); if (! cDevice::PrimaryDevice()->Replaying()) { bool isMute = cDevice::PrimaryDevice()->IsMute(); cDevice::PrimaryDevice()->SetVolume(ChVolume,1); if (isMute) cDevice::PrimaryDevice()->ToggleMute(); } ReplyCode = 900; return cString::sprintf("Set Volume to %d for channel %d", ChVolume, myChannelNr); } } ReplyCode = 501; return cString::sprintf("Illegal volume \"%s\"", p); } if ((p = strtok_r(NULL, delim, &strtok_next)) != NULL) { ReplyCode = 501; return cString::sprintf("Unexpected parameter \"%s\"", p); } } } //DEBUGSVDRP("Option:<%s> myChannelNr=%d\n", Option, myChannelNr); ReplyCode = 501; return cString::sprintf("Illegal channel \"%s\"", strChannel); } ReplyCode = 501; return cString::sprintf("Parameters missing\n"); } sAdvChCtrlConfig advchctrlConfig; VDRPLUGINCREATOR(cPluginAdvChCtrl); // Don't touch this!