aboutsummaryrefslogtreecommitdiff
path: root/src/utils/TuxBoxUtil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils/TuxBoxUtil.cpp')
-rw-r--r--src/utils/TuxBoxUtil.cpp1649
1 files changed, 1649 insertions, 0 deletions
diff --git a/src/utils/TuxBoxUtil.cpp b/src/utils/TuxBoxUtil.cpp
new file mode 100644
index 0000000000..70cc98e813
--- /dev/null
+++ b/src/utils/TuxBoxUtil.cpp
@@ -0,0 +1,1649 @@
+/*
+ * Copyright (C) 2005-2013 Team XBMC
+ * http://xbmc.org
+ *
+ * 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, 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 XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+//
+// GeminiServer
+//
+
+#include "TuxBoxUtil.h"
+#include "URIUtils.h"
+#include "filesystem/CurlFile.h"
+#include "dialogs/GUIDialogContextMenu.h"
+#include "Application.h"
+#include "ApplicationMessenger.h"
+#include "GUIInfoManager.h"
+#include "video/VideoInfoTag.h"
+#include "guilib/GUIWindowManager.h"
+#include "dialogs/GUIDialogOK.h"
+#include "dialogs/GUIDialogYesNo.h"
+#include "filesystem/File.h"
+#include "URL.h"
+#include "settings/AdvancedSettings.h"
+#include "FileItem.h"
+#include "guilib/LocalizeStrings.h"
+#include "StringUtils.h"
+#include "utils/XBMCTinyXML.h"
+#include "utils/XMLUtils.h"
+#include "log.h"
+
+using namespace XFILE;
+using namespace std;
+
+CTuxBoxUtil g_tuxbox;
+CTuxBoxService g_tuxboxService;
+
+CTuxBoxService::CTuxBoxService() : CThread("TuxBoxService")
+{
+}
+CTuxBoxService::~CTuxBoxService()
+{
+}
+CTuxBoxUtil::CTuxBoxUtil(void)
+{
+ sCurSrvData.requested_audio_channel = 0;
+ vVideoSubChannel.mode = false;
+ sZapstream.initialized = false;
+ sZapstream.available = false;
+}
+CTuxBoxUtil::~CTuxBoxUtil(void)
+{
+}
+bool CTuxBoxService::Start()
+{
+ if(g_advancedSettings.m_iTuxBoxEpgRequestTime != 0)
+ {
+ StopThread();
+ Create(false);
+ return true;
+ }
+ else
+ return false;
+}
+void CTuxBoxService::Stop()
+{
+ CLog::Log(LOGDEBUG, "%s - Stopping CTuxBoxService thread", __FUNCTION__);
+ StopThread();
+}
+void CTuxBoxService::OnStartup()
+{
+ CLog::Log(LOGDEBUG, "%s - Starting CTuxBoxService thread", __FUNCTION__);
+ SetPriority( GetMinPriority() );
+}
+void CTuxBoxService::OnExit()
+{
+ CThread::m_bStop = true;
+}
+bool CTuxBoxService::IsRunning()
+{
+ return !CThread::m_bStop;
+}
+void CTuxBoxService::Process()
+{
+ std::string strCurrentServiceName = g_tuxbox.sCurSrvData.service_name;
+ std::string strURL;
+
+ while(!CThread::m_bStop && g_application.m_pPlayer->IsPlaying())
+ {
+ strURL = g_application.CurrentFileItem().GetPath();
+ if(!URIUtils::IsTuxBox(strURL))
+ break;
+
+ int iRequestTimer = g_advancedSettings.m_iTuxBoxEpgRequestTime *1000; //seconds
+ Sleep(iRequestTimer);
+
+ CURL url(strURL);
+ if(g_tuxbox.GetHttpXML(url,"currentservicedata"))
+ {
+ CLog::Log(LOGDEBUG, "%s - receive current service data was successful", __FUNCTION__);
+ if(!strCurrentServiceName.empty()&&
+ strCurrentServiceName != "NULL" &&
+ !g_tuxbox.sCurSrvData.service_name.empty() &&
+ g_tuxbox.sCurSrvData.service_name != "-" &&
+ !g_tuxbox.vVideoSubChannel.mode)
+ {
+ //Detect Channel Change
+ //We need to detect the channel on the TuxBox Device!
+ //On changing the channel on the device we will loose the stream and mplayer seems not able to detect it to stop
+ if (strCurrentServiceName != g_tuxbox.sCurSrvData.service_name && g_application.m_pPlayer->IsPlaying() && !g_tuxbox.sZapstream.available)
+ {
+ CLog::Log(LOGDEBUG," - ERROR: Non controlled channel change detected! Stopping current playing stream!");
+ CApplicationMessenger::Get().MediaStop();
+ break;
+ }
+ }
+ //Update infomanager from tuxbox client
+ g_infoManager.UpdateFromTuxBox();
+ }
+ else
+ CLog::Log(LOGDEBUG, "%s - Could not receive current service data", __FUNCTION__);
+ }
+}
+bool CTuxBoxUtil::CreateNewItem(const CFileItem& item, CFileItem& item_new)
+{
+ //Build new Item
+ item_new.SetLabel(item.GetLabel());
+ item_new.SetPath(item.GetPath());
+ item_new.SetArt("thumb", item.GetArt("thumb"));
+
+ if(g_tuxbox.GetZapUrl(item.GetPath(), item_new))
+ {
+ if(vVideoSubChannel.mode)
+ vVideoSubChannel.current_name = item_new.GetLabel()+" ("+vVideoSubChannel.current_name+")";
+ return true;
+ }
+ else
+ {
+ if(sBoxStatus.recording != "1") //Don't Show this Dialog, if the Box is in Recording mode! A previos YN Dialog was send to user!
+ {
+ CLog::Log(LOGDEBUG, "%s ---------------------------------------------------------", __FUNCTION__);
+ CLog::Log(LOGDEBUG, "%s - WARNING: Zaping Failed no Zap Point found!", __FUNCTION__);
+ CLog::Log(LOGDEBUG, "%s ---------------------------------------------------------", __FUNCTION__);
+ std::string strText = StringUtils::Format(g_localizeStrings.Get(21334).c_str(), item.GetLabel().c_str());
+ CGUIDialogOK::ShowAndGetInput(21331, strText, 21333, 0);
+ }
+ }
+ return false;
+}
+bool CTuxBoxUtil::ParseBouquets(TiXmlElement *root, CFileItemList &items, CURL &url, std::string strFilter, std::string strChild)
+{
+ std::string strOptions;
+ TiXmlElement *pRootElement =root;
+ TiXmlNode *pNode = NULL;
+ TiXmlNode *pIt = NULL;
+ items.m_idepth =1;
+ // Get Options
+ strOptions = url.GetOptions();
+
+ if (!pRootElement)
+ {
+ CLog::Log(LOGWARNING, "%s - No %s found", __FUNCTION__, strChild.c_str());
+ return false;
+ }
+ if (strFilter.empty())
+ {
+ pNode = pRootElement->FirstChild(strChild.c_str());
+ if (!pNode)
+ {
+ CLog::Log(LOGWARNING, "%s - No %s found", __FUNCTION__,strChild.c_str());
+ return false;
+ }
+ while(pNode)
+ {
+ pIt = pNode->FirstChild("name");
+ if (pIt)
+ {
+ std::string strItemName = pIt->FirstChild()->Value();
+
+ pIt = pNode->FirstChild("reference");
+ if (pIt)
+ {
+ std::string strItemPath = pIt->FirstChild()->Value();
+ // add. bouquets to item list!
+ CFileItemPtr pItem(new CFileItem);
+ pItem->m_bIsFolder = true;
+ pItem->SetLabel(strItemName);
+ {
+ CURL fileUrl;
+ fileUrl.SetProtocol("tuxbox");
+ fileUrl.SetUserName(url.GetUserName());
+ fileUrl.SetPassword(url.GetPassWord());
+ fileUrl.SetHostName(url.GetHostName());
+ if (url.GetPort() != 0 && url.GetPort() != 80)
+ fileUrl.SetPort(url.GetPort());
+ fileUrl.SetOptions(url.GetOptions());
+ fileUrl.SetOption("reference", strItemPath);
+ pItem->SetPath(fileUrl.Get());
+ }
+ items.Add(pItem);
+ //DEBUG Log
+ CLog::Log(LOGDEBUG, "%s - Name: %s", __FUNCTION__,strItemName.c_str());
+ CLog::Log(LOGDEBUG, "%s - Adress: %s", __FUNCTION__,pItem->GetPath().c_str());
+ }
+ }
+ pNode = pNode->NextSibling(strChild.c_str());
+ }
+ }
+ return true;
+}
+bool CTuxBoxUtil::ParseBouquetsEnigma2(TiXmlElement *root, CFileItemList &items, CURL &url, std::string& strFilter, std::string& strChild)
+{
+ TiXmlElement *pRootElement = root;
+ TiXmlNode *pNode = NULL;
+ TiXmlNode *pIt = NULL;
+ items.m_idepth = 1;
+
+ if (!pRootElement)
+ {
+ CLog::Log(LOGWARNING, "%s - No %s found", __FUNCTION__, strChild.c_str());
+ return false;
+ }
+ if (strFilter.empty())
+ {
+ pNode = pRootElement->FirstChildElement("e2bouquet");
+ if (!pNode)
+ {
+ CLog::Log(LOGWARNING, "%s - No %s found", __FUNCTION__,strChild.c_str());
+ return false;
+ }
+ while(pNode)
+ {
+ CFileItemPtr pItem(new CFileItem);
+ pIt = pNode->FirstChildElement("e2servicereference");
+ std::string strItemPath = pIt->FirstChild()->Value();
+ pIt = pNode->FirstChildElement("e2servicename");
+ std::string strItemName = pIt->FirstChild()->Value();
+ pItem->m_bIsFolder = true;
+ pItem->SetLabel(strItemName);
+ {
+ CURL fileUrl;
+ fileUrl.SetProtocol("tuxbox");
+ fileUrl.SetHostName(url.GetHostName());
+ if (url.GetPort() != 0 && url.GetPort() != 80)
+ fileUrl.SetPort(url.GetPort());
+ fileUrl.SetFileName(strItemName + "/");
+ pItem->SetPath(fileUrl.Get());
+ }
+ items.Add(pItem);
+ pNode = pNode->NextSiblingElement("e2bouquet");
+ }
+ }
+ return true;
+}
+bool CTuxBoxUtil::ParseChannels(TiXmlElement *root, CFileItemList &items, CURL &url, std::string strFilter, std::string strChild)
+{
+ TiXmlElement *pRootElement =root;
+ TiXmlNode *pNode = NULL;
+ TiXmlNode *pIt = NULL;
+ TiXmlNode *pIta = NULL;
+ items.m_idepth =2;
+
+ if (!pRootElement)
+ {
+ CLog::Log(LOGWARNING, "%s - No %ss found", __FUNCTION__,strChild.c_str());
+ return false;
+ }
+ if(!strFilter.empty())
+ {
+ pNode = pRootElement->FirstChild(strChild.c_str());
+ if (!pNode)
+ {
+ CLog::Log(LOGWARNING, "%s - No %s found", __FUNCTION__,strChild.c_str());
+ return false;
+ }
+ while(pNode)
+ {
+ pIt = pNode->FirstChild("name");
+ if (pIt)
+ {
+ std::string strItemName = pIt->FirstChild()->Value();
+
+ pIt = pNode->FirstChild("reference");
+ if (strFilter == pIt->FirstChild()->Value())
+ {
+ pIt = pNode->FirstChild("service");
+ if (!pIt)
+ {
+ CLog::Log(LOGWARNING, "%s - No service found", __FUNCTION__);
+ return false;
+ }
+ while(pIt)
+ {
+ pIta = pIt->FirstChild("name");
+ if (pIta)
+ {
+ strItemName = pIta->FirstChild()->Value();
+
+ pIta = pIt->FirstChild("reference");
+ if (pIta)
+ {
+ std::string strItemPath = pIta->FirstChild()->Value();
+ // channel listing add. to item list!
+ CFileItemPtr pbItem(new CFileItem);
+ pbItem->m_bIsFolder = false;
+ pbItem->SetLabel(strItemName);
+ pbItem->SetLabelPreformated(true);
+ {
+ CURL fileUrl;
+ fileUrl.SetProtocol("tuxbox");
+ fileUrl.SetUserName(url.GetUserName());
+ fileUrl.SetPassword(url.GetPassWord());
+ fileUrl.SetHostName(url.GetHostName());
+ if (url.GetPort() != 0 && url.GetPort() != 80)
+ fileUrl.SetPort(url.GetPort());
+ fileUrl.SetFileName("cgi-bin/zapTo");
+ fileUrl.SetOption("path", strItemPath+".ts");
+ pbItem->SetPath(fileUrl.Get());
+ }
+ pbItem->SetArt("thumb", GetPicon(strItemName)); //Set Picon Image
+
+ //DEBUG Log
+ CLog::Log(LOGDEBUG, "%s - Name: %s", __FUNCTION__,strItemName.c_str());
+ CLog::Log(LOGDEBUG, "%s - Adress: %s", __FUNCTION__,pbItem->GetPath().c_str());
+
+ //add to the list
+ items.Add(pbItem);
+ }
+ }
+ pIt = pIt->NextSibling("service");
+ }
+ }
+ }
+ pNode = pNode->NextSibling(strChild.c_str());
+ }
+ return true;
+ }
+ return false;
+}
+bool CTuxBoxUtil::ParseChannelsEnigma2(TiXmlElement *root, CFileItemList &items, CURL &url, std::string& strFilter, std::string& strChild)
+{
+ TiXmlElement *pRootElement = root;
+ TiXmlNode *pNode = NULL;
+ TiXmlNode *pIt = NULL;
+ TiXmlNode *pIta = NULL;
+ TiXmlNode *pItb = NULL;
+ items.m_idepth = 2;
+
+ if (!pRootElement)
+ {
+ CLog::Log(LOGWARNING, "%s - No %ss found", __FUNCTION__,strChild.c_str());
+ return false;
+ }
+ if(!strFilter.empty())
+ {
+ pNode = pRootElement->FirstChild(strChild.c_str());
+ if (!pNode)
+ {
+ CLog::Log(LOGWARNING, "%s - No %s found", __FUNCTION__,strChild.c_str());
+ return false;
+ }
+ while(pNode)
+ {
+ pIt = pNode->FirstChildElement("e2servicename");
+ std::string bqtName = pIt->FirstChild()->Value();
+ pIt = pNode->FirstChildElement("e2servicelist");
+ pIta = pIt->FirstChildElement("e2service");
+ while(pIta)
+ {
+ pItb = pIta->FirstChildElement("e2servicereference");
+ std::string strItemPath = pItb->FirstChild()->Value();
+ pItb = pIta->FirstChildElement("e2servicename");
+ std::string strItemName = pItb->FirstChild()->Value();
+ if(bqtName == url.GetShareName())
+ {
+ CFileItemPtr pbItem(new CFileItem);
+ pbItem->m_bIsFolder = false;
+ pbItem->SetLabel(strItemName);
+ {
+ CURL fileUrl;
+ fileUrl.SetProtocol("http");
+ fileUrl.SetHostName(url.GetHostName());
+ fileUrl.SetPort(8001);
+ fileUrl.SetFileName(strItemPath);
+ pbItem->SetPath(fileUrl.Get());
+ }
+ pbItem->SetMimeType("video/mpeg2");
+ items.Add(pbItem);
+ CLog::Log(LOGDEBUG, "%s - Name: %s", __FUNCTION__,strItemName.c_str());
+ CLog::Log(LOGDEBUG, "%s - Adress: %s", __FUNCTION__,pbItem->GetPath().c_str());
+ }
+ pIta = pIta->NextSiblingElement("e2service");
+ }
+ pNode = pNode->NextSiblingElement("e2bouquet");
+ }
+ }
+ return true;
+}
+bool CTuxBoxUtil::ZapToUrl(CURL url, const std::string &pathOption)
+{
+ // send Zap
+ //Extract the ZAP to Service String
+ //Remove the ".ts"
+ std::string strFilter = pathOption.substr(0, pathOption.size() - 3);
+ //Get the Service Name
+
+ // Create ZAP URL
+ CURL urlx;
+ urlx.SetProtocol("http");
+ urlx.SetUserName(url.GetUserName());
+ urlx.SetPassword(url.GetPassWord());
+ urlx.SetHostName(url.GetHostName());
+ if (url.GetPort() != 0 && url.GetPort() != 80)
+ urlx.SetPort(url.GetPort());
+ CURL postUrl(urlx);
+ postUrl.SetFileName("cgi-bin/zapTo");
+ postUrl.SetOption("path", strFilter);
+
+ //Check Recording State!
+ if(GetHttpXML(urlx,"boxstatus"))
+ {
+ if(sBoxStatus.recording == "1")
+ {
+ CLog::Log(LOGDEBUG, "%s ---------------------------------------------------------", __FUNCTION__);
+ CLog::Log(LOGDEBUG, "%s - WARNING: Device is Recording! Record Mode is: %s", __FUNCTION__,sBoxStatus.recording.c_str());
+ CLog::Log(LOGDEBUG, "%s ---------------------------------------------------------", __FUNCTION__);
+ CGUIDialogYesNo* dialog = (CGUIDialogYesNo*)g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO);
+ if (dialog)
+ {
+ //Target TuxBox is in Recording mode! Are you sure to stream ?YN
+ dialog->SetHeading(21331);
+ dialog->SetLine( 0, 21332);
+ dialog->SetLine( 1, 21335);
+ dialog->SetLine( 2, "" );
+ dialog->DoModal();
+ if (!dialog->IsConfirmed())
+ {
+ //DialogYN = NO -> Return false!
+ return false;
+ }
+ }
+ }
+ }
+
+ //Send ZAP Command
+ CCurlFile http;
+ if(http.Open(postUrl))
+ {
+ //DEBUG LOG
+ CLog::Log(LOGDEBUG, "%s - Zapped to: %s", __FUNCTION__,postUrl.Get().c_str());
+
+ //Request StreamInfo
+ GetHttpXML(urlx,"streaminfo");
+
+ //Extract StreamInformations
+ int iRetry=0;
+ //PMT must be a valid value to be sure that the ZAP is OK and we can stream!
+ while(sStrmInfo.pmt == "ffffffffh" && iRetry!=10) //try 10 Times
+ {
+ CLog::Log(LOGDEBUG, "%s - Requesting STREAMINFO! TryCount: %i!", __FUNCTION__,iRetry);
+ GetHttpXML(urlx,"streaminfo");
+ iRetry=iRetry+1;
+ Sleep(200);
+ }
+
+ // PMT Not Valid? Try Time 10 reached, checking for advancedSettings m_iTuxBoxZapWaitTime
+ if(sStrmInfo.pmt == "ffffffffh" && g_advancedSettings.m_iTuxBoxZapWaitTime > 0 )
+ {
+ iRetry = 0;
+ CLog::Log(LOGDEBUG, "%s - Starting TuxBox ZapWaitTimer!", __FUNCTION__);
+ while(sStrmInfo.pmt == "ffffffffh" && iRetry!=10) //try 10 Times
+ {
+ CLog::Log(LOGDEBUG, "%s - Requesting STREAMINFO! TryCount: %i!", __FUNCTION__,iRetry);
+ GetHttpXML(urlx,"streaminfo");
+ iRetry=iRetry+1;
+ if(sStrmInfo.pmt == "ffffffffh")
+ {
+ CLog::Log(LOGERROR, "%s - STREAMINFO ERROR! Could not receive all data, TryCount: %i!", __FUNCTION__,iRetry);
+ CLog::Log(LOGERROR, "%s - PMT is: %s (not a Valid Value)! Waiting %i sec.", __FUNCTION__,sStrmInfo.pmt.c_str(), g_advancedSettings.m_iTuxBoxZapWaitTime);
+ Sleep(g_advancedSettings.m_iTuxBoxZapWaitTime*1000);
+ }
+ }
+ }
+
+ //PMT Failed! No StreamInformations availible.. closing stream
+ if (sStrmInfo.pmt == "ffffffffh")
+ {
+ CLog::Log(LOGERROR, "%s-------------------------------------------------------------", __FUNCTION__);
+ CLog::Log(LOGERROR, "%s - STREAMINFO ERROR! Could not receive all data, TryCount: %i!", __FUNCTION__,iRetry);
+ CLog::Log(LOGERROR, "%s - PMT is: %s (not a Valid Value)! There is nothing to Stream!", __FUNCTION__,sStrmInfo.pmt.c_str());
+ CLog::Log(LOGERROR, "%s - The Stream will stopped!", __FUNCTION__);
+ CLog::Log(LOGERROR, "%s-------------------------------------------------------------", __FUNCTION__);
+ return false;
+ }
+ //Currentservicedata
+ GetHttpXML(urlx,"currentservicedata");
+ //boxstatus
+ GetHttpXML(urlx,"boxstatus");
+ //boxinfo
+ GetHttpXML(urlx,"boxinfo");
+ //serviceepg
+ GetHttpXML(urlx,"serviceepg");
+ return true;
+ }
+ return false;
+}
+bool CTuxBoxUtil::GetZapUrl(const std::string& strPath, CFileItem &items )
+{
+ CURL url(strPath);
+ std::string strOptions = url.GetOptions();
+ if (strOptions.empty())
+ return false;
+
+ if (url.HasOption("path"))
+ {
+ if(ZapToUrl(url, url.GetOption("path")))
+ {
+ //Check VideoSubChannels
+ if(GetHttpXML(url,"currentservicedata")) //Update Currentservicedata
+ {
+ //Detect VideoSubChannels
+ std::string strVideoSubChannelName, strVideoSubChannelPID;
+ if(GetVideoSubChannels(strVideoSubChannelName,strVideoSubChannelPID ))
+ {
+ // new videosubchannel selected! settings options to new video zap id
+ // zap again now to new videosubchannel
+ if(ZapToUrl(url, strVideoSubChannelPID + ".ts"))
+ {
+ vVideoSubChannel.mode = true;
+ vVideoSubChannel.current_name = strVideoSubChannelName;
+ }
+ }
+ else
+ vVideoSubChannel.mode= false;
+ }
+
+ std::string strVideoStream;
+ std::string strLabel, strLabel2;
+ std::string strAudioChannelPid;
+ std::string strAPids;
+ sAudioChannel sRequestedAudioChannel;
+
+ if (!GetGUIRequestedAudioChannel(sRequestedAudioChannel))
+ {
+ if (g_advancedSettings.m_bTuxBoxSendAllAPids && sCurSrvData.audio_channels.size() > 1)
+ {
+ for (vector<sAudioChannel>::iterator sChannel = sCurSrvData.audio_channels.begin(); sChannel!=sCurSrvData.audio_channels.end(); ++sChannel)
+ {
+ if (sChannel->pid != sRequestedAudioChannel.pid && sChannel->pid.size() >= 4)
+ strAPids += "," + sChannel->pid.substr(sChannel->pid.size() - 4);
+ }
+ CLog::Log(LOGDEBUG, "%s - Sending all audio pids: %s%s", __FUNCTION__, strAudioChannelPid.c_str(), strAPids.c_str());
+
+ strVideoStream = StringUtils::Format("0,%s,%s,%s%s",
+ sStrmInfo.pmt.substr(0, 4).c_str(),
+ sStrmInfo.vpid.substr(0, 4).c_str(),
+ sStrmInfo.apid.substr(0, 4).c_str(),
+ strAPids.c_str());
+ }
+ else
+ strVideoStream = StringUtils::Format("0,%s,%s,%s",
+ sStrmInfo.pmt.substr(0, 4).c_str(),
+ sStrmInfo.vpid.substr(0, 4).c_str(),
+ sStrmInfo.apid.substr(0, 4).c_str());
+ }
+ else
+ strVideoStream = StringUtils::Format("0,%s,%s,%s",
+ sStrmInfo.pmt.substr(0, 4).c_str(),
+ sStrmInfo.vpid.substr(0, 4).c_str(),
+ strAudioChannelPid.substr(0, 4).c_str());
+
+ CURL streamURL;
+ streamURL.SetProtocol("http");
+ streamURL.SetUserName(url.GetUserName());
+ streamURL.SetPassword(url.GetPassWord());
+ streamURL.SetHostName(url.GetHostName());
+ streamURL.SetPort(g_advancedSettings.m_iTuxBoxStreamtsPort);
+ streamURL.SetFileName(strVideoStream.c_str());
+
+ if (!g_tuxbox.sZapstream.initialized)
+ g_tuxbox.InitZapstream(strPath);
+
+ // Use the Zapstream service when available.
+ if (g_tuxbox.sZapstream.available)
+ {
+ sAudioChannel sSelectedAudioChannel;
+ if (GetRequestedAudioChannel(sSelectedAudioChannel))
+ {
+ if (sSelectedAudioChannel.pid != sStrmInfo.apid)
+ {
+ if (SetAudioChannel(strPath, sSelectedAudioChannel))
+ CLog::Log(LOGDEBUG, "%s - Zapstream: Requested audio channel is %s, pid %s.", __FUNCTION__, sSelectedAudioChannel.name.c_str(), sSelectedAudioChannel.pid.c_str());
+ }
+ }
+ streamURL.SetFileName("");
+ streamURL.SetPort(g_advancedSettings.m_iTuxBoxZapstreamPort);
+ }
+
+ if (g_application.m_pPlayer->IsPlaying() && !g_tuxbox.sZapstream.available)
+ CApplicationMessenger::Get().MediaStop();
+
+ strLabel = StringUtils::Format("%s: %s %s-%s",
+ items.GetLabel().c_str(),
+ sCurSrvData.current_event_date.c_str(),
+ sCurSrvData.current_event_start.c_str(),
+ sCurSrvData.current_event_start.c_str());
+ strLabel2 = StringUtils::Format("%s", sCurSrvData.current_event_description.c_str());
+
+ // Set Event details
+ std::string strGenre, strTitle;
+ strGenre = StringUtils::Format("%s %s - (%s: %s)",
+ g_localizeStrings.Get(143).c_str(), sCurSrvData.current_event_description.c_str(),
+ g_localizeStrings.Get(209).c_str(), sCurSrvData.next_event_description.c_str());
+ strTitle = StringUtils::Format("%s", sCurSrvData.current_event_details.c_str());
+ int iDuration = atoi(sCurSrvData.current_event_duration.c_str());
+
+ items.GetVideoInfoTag()->m_genre = StringUtils::Split(strGenre, g_advancedSettings.m_videoItemSeparator); // VIDEOPLAYER_GENRE: current_event_description (Film Name)
+ items.GetVideoInfoTag()->m_strTitle = strTitle; // VIDEOPLAYER_TITLE: current_event_details (Film beschreibung)
+ items.GetVideoInfoTag()->m_duration = iDuration; //VIDEOPLAYER_DURATION: current_event_duration (laufzeit in sec.)
+
+ items.SetPath(streamURL.Get());
+ items.m_iDriveType = url.GetPort(); // Dirty Hack! But i need to hold the Port ;)
+ items.SetLabel(items.GetLabel()); // VIDEOPLAYER_DIRECTOR: service_name (Program Name)
+ items.SetLabel2(sCurSrvData.current_event_description); // current_event_description (Film Name)
+ items.m_bIsFolder = false;
+ items.SetMimeType("video/x-mpegts");
+ return true;
+ }
+ }
+ return false;
+}
+
+// Notice: Zapstream is a streamts enhancement from PLi development team.
+// If you are using a non-PLi based image you might not have Zapstream installed.
+bool CTuxBoxUtil::InitZapstream(const std::string& strPath)
+{
+ CURL url(strPath);
+ CCurlFile http;
+ int iTryConnect = 0;
+ int iTimeout = 2;
+
+ g_tuxbox.sZapstream.initialized = true;
+
+ if (!g_advancedSettings.m_bTuxBoxZapstream)
+ {
+ CLog::Log(LOGDEBUG, "%s - Zapstream is disabled in advancedsettings.xml.", __FUNCTION__);
+ return g_tuxbox.sZapstream.available = false;
+ }
+
+ url.SetProtocol("http");
+ url.SetFileName("");
+ url.SetOptions("");
+ url.SetPort(g_advancedSettings.m_iTuxBoxZapstreamPort);
+
+ while (iTryConnect < 3)
+ {
+ http.SetTimeout(iTimeout);
+
+ if (http.Open(url))
+ {
+ http.Close();
+ CHttpHeader h = http.GetHttpHeader();
+ std::string strValue = h.GetValue("server");
+
+ if (strValue.find("zapstream") != std::string::npos)
+ {
+ CLog::Log(LOGDEBUG, "%s - Zapstream is available on port %i.", __FUNCTION__, g_advancedSettings.m_iTuxBoxZapstreamPort);
+ return g_tuxbox.sZapstream.available = true;
+ }
+ }
+
+ iTryConnect++;
+ iTimeout+=5;
+ }
+
+ CLog::Log(LOGDEBUG, "%s - Zapstream is not available on port %i.", __FUNCTION__, g_advancedSettings.m_iTuxBoxZapstreamPort);
+ return false;
+}
+bool CTuxBoxUtil::SetAudioChannel( const std::string& strPath, const AUDIOCHANNEL& sAC )
+{
+ CURL url(strPath);
+ CCurlFile http;
+ int iTryConnect = 0;
+ int iTimeout = 2;
+
+ url.SetProtocol("http");
+ url.SetFileName("cgi-bin/setAudio");
+ url.SetOptions("?channel=1&language=" + sAC.pid);
+ url.SetPort(80);
+
+ g_tuxbox.sZapstream.initialized = true;
+
+ while (iTryConnect < 3)
+ {
+ http.SetTimeout(iTimeout);
+
+ if (http.Open(url))
+ {
+ http.Close();
+ return true;
+ }
+
+ iTryConnect++;
+ iTimeout+=5;
+ }
+
+ return false;
+}
+bool CTuxBoxUtil::GetHttpXML(CURL url,std::string strRequestType)
+{
+ // Check and Set URL Request Option
+ if(!strRequestType.empty())
+ {
+ if(strRequestType == "streaminfo")
+ {
+ url.SetOptions("xml/streaminfo");
+ }
+ else if(strRequestType == "currentservicedata")
+ {
+ url.SetOptions("xml/currentservicedata");
+ }
+ else if(strRequestType == "boxstatus")
+ {
+ url.SetOptions("xml/boxstatus");
+ }
+ else if(strRequestType == "boxinfo")
+ {
+ url.SetOptions("xml/boxinfo");
+ }
+ else if(strRequestType == "serviceepg")
+ {
+ url.SetOptions("xml/serviceepg");
+ }
+ else
+ {
+ CLog::Log(LOGERROR, "%s - Request Type is not defined! You requested: %s", __FUNCTION__,strRequestType.c_str());
+ return false;
+ }
+ }
+ else
+ {
+ CLog::Log(LOGERROR, "%s - strRequestType Request Type is Empty!", __FUNCTION__);
+ return false;
+ }
+
+ // Clean Up the URL, so we have a clean request!
+ url.SetFileName("");
+
+ //Open
+ CCurlFile http;
+ http.SetTimeout(20);
+ if(http.Open(url))
+ {
+ int size_read = 0;
+ int size_total = (int)http.GetLength();
+
+ if(size_total > 0)
+ {
+ // read response from server into string buffer
+ std::string strTmp;
+ strTmp.reserve(size_total);
+ char buffer[16384];
+ while( (size_read = http.Read( buffer, sizeof(buffer)-1) ) > 0 )
+ {
+ buffer[size_read] = 0;
+ strTmp += buffer;
+ }
+
+ // parse returned xml
+ CXBMCTinyXML doc;
+ TiXmlElement *XMLRoot=NULL;
+ StringUtils::Replace(strTmp, "></",">-</"); //FILL EMPTY ELEMENTS WITH "-"!
+ doc.Parse(strTmp, http.GetServerReportedCharset());
+ strTmp.clear();
+
+ XMLRoot = doc.RootElement();
+ std::string strRoot = XMLRoot->Value();
+ if( strRoot == "streaminfo")
+ return StreamInformations(XMLRoot);
+ if(strRoot == "currentservicedata")
+ return CurrentServiceData(XMLRoot);
+ if(strRoot == "boxstatus")
+ return BoxStatus(XMLRoot);
+ if(strRoot == "boxinfo")
+ return BoxInfo(XMLRoot);
+ if(strRoot == "serviceepg" ||
+ strRoot == "service_epg")
+ return ServiceEPG(XMLRoot);
+
+ CLog::Log(LOGERROR, "%s - Unable to parse xml", __FUNCTION__);
+ CLog::Log(LOGERROR, "%s - Request String: %s", __FUNCTION__,strRoot.c_str());
+ return false;
+ }
+ else
+ {
+ CLog::Log(LOGERROR, "%s - http length is invalid!", __FUNCTION__);
+ return false;
+ }
+ }
+ CLog::Log(LOGERROR, "%s - Open URL Failed! Unable to get XML structure", __FUNCTION__);
+ return false;
+}
+bool CTuxBoxUtil::StreamInformations(TiXmlElement *pRootElement)
+{
+ /*
+ Sample:
+ http://192.168.0.110:31339/0,0065,01ff,0200,0201,0203,01ff
+
+ http://getIP:31339/0,pmtpid,vpid,apid,apids,apids,pcrpid;
+
+ vpid,pmtpid,pcrpid,apid --> xml/streaminfo
+ apids --> /xml/currentservicedata
+
+ apid: is the defined audio stream!
+ Normal Stereo: http://192.168.0.110:31339/0,0065,01ff,0200,0201,0203,01ff
+ Normal English: http://192.168.0.110:31339/0,0065,01ff,0201,,,01ff
+ Normal DD5.1/AC3: http://192.168.0.110:31339/0,0065,01ff,0203,,,01ff
+ */
+
+ TiXmlNode *pNode = NULL;
+ TiXmlNode *pIt = NULL;
+ if(pRootElement != NULL)
+ {
+ pNode = pRootElement->FirstChild("frontend");
+ if (pNode)
+ {
+ sStrmInfo.frontend = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Frontend: %s", __FUNCTION__, sStrmInfo.frontend.c_str());
+ }
+ pNode = pRootElement->FirstChild("service");
+ if (pNode)
+ {
+ CLog::Log(LOGDEBUG, "%s - Service", __FUNCTION__);
+ pIt = pNode->FirstChild("name");
+ if (pIt)
+ {
+ sStrmInfo.service_name = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Name: %s", __FUNCTION__, sStrmInfo.service_name.c_str());
+ }
+ pIt = pNode->FirstChild("reference");
+ if (pIt)
+ {
+ sStrmInfo.service_reference = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Reference: %s", __FUNCTION__, sStrmInfo.service_reference.c_str());
+ }
+ }
+
+ pNode = pRootElement->FirstChild("provider");
+ if(pNode && pNode->FirstChild())
+ {
+ sStrmInfo.provider= pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Provider: %s", __FUNCTION__, sStrmInfo.provider.c_str());
+ }
+ pNode = pRootElement->FirstChild("vpid");
+ if (pNode)
+ {
+ sStrmInfo.vpid = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Vpid: %s", __FUNCTION__, sStrmInfo.vpid.c_str());
+ }
+ pNode = pRootElement->FirstChild("apid");
+ if (pNode)
+ {
+ sStrmInfo.apid = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Apid: %s", __FUNCTION__, sStrmInfo.apid.c_str());
+ }
+ pNode = pRootElement->FirstChild("pcrpid");
+ if (pNode)
+ {
+ sStrmInfo.pcrpid = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - PcrPid: %s", __FUNCTION__, sStrmInfo.pcrpid.c_str());
+ }
+ pNode = pRootElement->FirstChild("tpid");
+ if (pNode)
+ {
+ sStrmInfo.tpid = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Tpid: %s", __FUNCTION__, sStrmInfo.tpid.c_str());
+ }
+ pNode = pRootElement->FirstChild("tsid");
+ if (pNode)
+ {
+ sStrmInfo.tsid = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Tsid: %s", __FUNCTION__, sStrmInfo.tsid.c_str());
+ }
+ pNode = pRootElement->FirstChild("onid");
+ if (pNode)
+ {
+ sStrmInfo.onid = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Onid: %s", __FUNCTION__, sStrmInfo.onid.c_str());
+ }
+ pNode = pRootElement->FirstChild("sid");
+ if (pNode)
+ {
+ sStrmInfo.sid = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Sid: %s", __FUNCTION__, sStrmInfo.sid.c_str());
+ }
+ pNode = pRootElement->FirstChild("pmt");
+ if (pNode)
+ {
+ sStrmInfo.pmt = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Pmt: %s", __FUNCTION__, sStrmInfo.pmt.c_str());
+ }
+ pNode = pRootElement->FirstChild("video_format");
+ if (pNode)
+ {
+ sStrmInfo.video_format = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Video Format: %s", __FUNCTION__, sStrmInfo.video_format.c_str());
+ }
+ pNode = pRootElement->FirstChild("supported_crypt_systems");
+ if (pNode)
+ {
+ sStrmInfo.supported_crypt_systems = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Supported Crypt Systems: %s", __FUNCTION__, sStrmInfo.supported_crypt_systems.c_str());
+ }
+ pNode = pRootElement->FirstChild("used_crypt_systems");
+ if (pNode)
+ {
+ sStrmInfo.used_crypt_systems = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Used Crypt Systems: %s", __FUNCTION__, sStrmInfo.used_crypt_systems.c_str());
+ }
+ pNode = pRootElement->FirstChild("satellite");
+ if (pNode)
+ {
+ sStrmInfo.satellite = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Satellite: %s", __FUNCTION__, sStrmInfo.satellite.c_str());
+ }
+ pNode = pRootElement->FirstChild("frequency");
+ if (pNode)
+ {
+ sStrmInfo.frequency = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Frequency: %s", __FUNCTION__, sStrmInfo.frequency.c_str());
+ }
+ pNode = pRootElement->FirstChild("symbol_rate");
+ if (pNode)
+ {
+ sStrmInfo.symbol_rate = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Symbol Rate: %s", __FUNCTION__, sStrmInfo.symbol_rate.c_str());
+ }
+ pNode = pRootElement->FirstChild("polarisation");
+ if (pNode)
+ {
+ sStrmInfo.polarisation = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Polarisation: %s", __FUNCTION__, sStrmInfo.polarisation.c_str());
+ }
+ pNode = pRootElement->FirstChild("inversion");
+ if (pNode)
+ {
+ sStrmInfo.inversion = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Inversion: %s", __FUNCTION__, sStrmInfo.inversion.c_str());
+ }
+ pNode = pRootElement->FirstChild("fec");
+ if (pNode)
+ {
+ sStrmInfo.fec = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Fec: %s", __FUNCTION__, sStrmInfo.fec.c_str());
+ }
+ pNode = pRootElement->FirstChild("snr");
+ if (pNode)
+ {
+ sStrmInfo.snr = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Snr: %s", __FUNCTION__, sStrmInfo.snr.c_str());
+ }
+ pNode = pRootElement->FirstChild("agc");
+ if (pNode)
+ {
+ sStrmInfo.agc = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Agc: %s", __FUNCTION__, sStrmInfo.agc.c_str());
+ }
+ pNode = pRootElement->FirstChild("ber");
+ if (pNode)
+ {
+ sStrmInfo.ber = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - ber: %s", __FUNCTION__, sStrmInfo.ber.c_str());
+ }
+ pNode = pRootElement->FirstChild("lock");
+ if (pNode)
+ {
+ sStrmInfo.lock = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Lock: %s", __FUNCTION__, sStrmInfo.lock.c_str());
+ }
+ pNode = pRootElement->FirstChild("sync");
+ if (pNode)
+ {
+ sStrmInfo.sync = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Sync: %s", __FUNCTION__, sStrmInfo.sync.c_str());
+ }
+ return true;
+ }
+ return false;
+}
+bool CTuxBoxUtil::CurrentServiceData(TiXmlElement *pRootElement)
+{
+ TiXmlNode *pNode = NULL;
+ TiXmlNode *pIt = NULL;
+ TiXmlNode *pVal = NULL;
+ if(pRootElement)
+ {
+ CLog::Log(LOGDEBUG, "%s - Current Service Data", __FUNCTION__);
+ pNode = pRootElement->FirstChild("service");
+ if (pNode)
+ {
+ CLog::Log(LOGDEBUG, "%s - Service", __FUNCTION__);
+ pIt = pNode->FirstChild("name");
+ if (pIt)
+ {
+ sCurSrvData.service_name = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Service Name: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+ pIt = pNode->FirstChild("reference");
+ if (pIt)
+ {
+ sCurSrvData.service_reference = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Service Reference: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+ }
+
+ pNode = pRootElement->FirstChild("audio_channels");
+ if (pNode)
+ {
+ CLog::Log(LOGDEBUG, "%s - Audio Channels", __FUNCTION__);
+ int i = 0;
+
+ pIt = pNode->FirstChild("channel");
+ sCurSrvData.audio_channels.clear();
+
+ while(pIt)
+ {
+ sAudioChannel newChannel;
+
+ pVal = pIt->FirstChild("pid");
+ if(pVal)
+ newChannel.pid = pVal->FirstChild()->Value();
+
+ pVal = pIt->FirstChild("selected");
+ if(pVal)
+ newChannel.selected = pVal->FirstChild()->Value();
+
+ pVal = pIt->FirstChild("name");
+ if(pVal)
+ newChannel.name = pVal->FirstChild()->Value();
+
+ CLog::Log(LOGDEBUG, "%s - Audio Channels: Channel %i -> PID: %s Selected: %s Name: %s", __FUNCTION__, i, newChannel.pid.c_str(), newChannel.selected.c_str(), newChannel.name.c_str() );
+
+ i=i+1;
+ sCurSrvData.audio_channels.push_back( newChannel );
+ pIt = pIt->NextSibling("channel");
+ }
+ }
+ pNode = pRootElement->FirstChild("audio_track");
+ if (pNode)
+ {
+ sCurSrvData.audio_track = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Audio Track: %s", __FUNCTION__, pNode->FirstChild()->Value() );
+ }
+ pNode = pRootElement->FirstChild("video_channels");
+ if (pNode)
+ {
+ CLog::Log(LOGDEBUG, "%s - Video Channels", __FUNCTION__);
+ pIt = pNode->FirstChild("service");
+ if (pIt)
+ {
+ vVideoSubChannel.name.clear();
+ vVideoSubChannel.reference.clear();
+ vVideoSubChannel.selected.clear();
+ int i = 0;
+ while(pIt)
+ {
+ pVal = pIt->FirstChild("name");
+ if(pVal)
+ {
+ vVideoSubChannel.name.push_back(pVal->FirstChild()->Value());
+ CLog::Log(LOGDEBUG, "%s - Video Sub Channel %i: Name: %s", __FUNCTION__, i,pVal->FirstChild()->Value());
+ }
+ pVal = pIt->FirstChild("reference");
+ if(pVal)
+ {
+ vVideoSubChannel.reference.push_back(pVal->FirstChild()->Value());
+ CLog::Log(LOGDEBUG, "%s - Video Sub Channel %i: Reference: %s", __FUNCTION__, i,pVal->FirstChild()->Value());
+ }
+ pVal = pIt->FirstChild("selected");
+ if(pVal)
+ {
+ vVideoSubChannel.selected.push_back(pVal->FirstChild()->Value());
+ CLog::Log(LOGDEBUG, "%s - Video Sub Channel %i: Selected: %s", __FUNCTION__, i,pVal->FirstChild()->Value());
+ }
+ pIt = pIt->NextSibling("service");
+ i++;
+ }
+ }
+ else
+ {
+ vVideoSubChannel.name.clear();
+ vVideoSubChannel.reference.clear();
+ vVideoSubChannel.selected.clear();
+ }
+ }
+ pNode = pRootElement->FirstChild("current_event");
+ if (pNode)
+ {
+ CLog::Log(LOGDEBUG, "%s - Current Event", __FUNCTION__);
+ pIt = pNode->FirstChild("date");
+ if (pIt)
+ {
+ sCurSrvData.current_event_date = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Date: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+ pIt = pNode->FirstChild("time");
+ if (pIt)
+ {
+ sCurSrvData.current_event_time = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Time: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+
+ pIt = pNode->FirstChild("start");
+ if (pIt)
+ {
+ sCurSrvData.current_event_start = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Start: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+
+ pIt = pNode->FirstChild("duration");
+ if (pIt)
+ {
+ sCurSrvData.current_event_duration = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Duration: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+
+ pIt = pNode->FirstChild("description");
+ if (pIt)
+ {
+ sCurSrvData.current_event_description = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Description: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+ pIt = pNode->FirstChild("details");
+ if (pIt)
+ {
+ sCurSrvData.current_event_details = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Details: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+ }
+ pNode = pRootElement->FirstChild("next_event");
+ if (pNode)
+ {
+ CLog::Log(LOGDEBUG, "%s - Next Event", __FUNCTION__);
+ pIt = pNode->FirstChild("date");
+ if (pIt)
+ {
+ sCurSrvData.next_event_date = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Date: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+ pIt = pNode->FirstChild("time");
+ if (pIt)
+ {
+ sCurSrvData.next_event_time = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Time: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+
+ pIt = pNode->FirstChild("start");
+ if (pIt)
+ {
+ sCurSrvData.next_event_start = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Start: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+
+ pIt = pNode->FirstChild("duration");
+ if (pIt)
+ {
+ sCurSrvData.next_event_duration = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Duration: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+
+ pIt = pNode->FirstChild("description");
+ if (pIt)
+ {
+ sCurSrvData.next_event_description = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Description: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+ pIt = pNode->FirstChild("details");
+ if (pIt)
+ {
+ sCurSrvData.next_event_details = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Details: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+ }
+ return true;
+ }
+ return false;
+
+}
+bool CTuxBoxUtil::BoxStatus(TiXmlElement *pRootElement)
+{
+ //Tuxbox Controll Commands
+ /*
+ /cgi-bin/admin?command=wakeup
+ /cgi-bin/admin?command=standby
+ /cgi-bin/admin?command=shutdown
+ /cgi-bin/admin?command=reboot
+ /cgi-bin/admin?command=restart
+ */
+
+ TiXmlNode *pNode = NULL;
+
+ if(pRootElement)
+ {
+ CLog::Log(LOGDEBUG, "%s - BoxStatus", __FUNCTION__);
+ pNode = pRootElement->FirstChild("current_time");
+ if (pNode)
+ {
+ sBoxStatus.current_time = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Current Time: %s", __FUNCTION__, pNode->FirstChild()->Value());
+ }
+ pNode = pRootElement->FirstChild("standby");
+ if (pNode)
+ {
+ sBoxStatus.standby = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Standby: %s", __FUNCTION__, pNode->FirstChild()->Value());
+ }
+ pNode = pRootElement->FirstChild("recording");
+ if (pNode)
+ {
+ sBoxStatus.recording = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Recording: %s", __FUNCTION__, pNode->FirstChild()->Value());
+ }
+ pNode = pRootElement->FirstChild("mode");
+ if (pNode)
+ {
+ sBoxStatus.mode = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Mode: %s", __FUNCTION__, pNode->FirstChild()->Value());
+ }
+ pNode = pRootElement->FirstChild("ip");
+ if (pNode)
+ {
+ if (sBoxStatus.ip != pNode->FirstChild()->Value() )
+ {
+ g_tuxbox.sZapstream.initialized = false;
+ g_tuxbox.sZapstream.available = false;
+ }
+ sBoxStatus.ip = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Ip: %s", __FUNCTION__, pNode->FirstChild()->Value());
+ }
+ return true;
+ }
+ return false;
+}
+bool CTuxBoxUtil::BoxInfo(TiXmlElement *pRootElement)
+{
+ TiXmlNode *pNode = NULL;
+ TiXmlNode *pIt = NULL;
+
+ if(pRootElement)
+ {
+ CLog::Log(LOGDEBUG, "%s - BoxInfo", __FUNCTION__);
+ pNode = pRootElement->FirstChild("image");
+ if (pNode)
+ {
+ CLog::Log(LOGDEBUG, "%s - Image", __FUNCTION__);
+ pIt = pNode->FirstChild("version");
+ if (pIt)
+ {
+ sBoxInfo.image_version = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Image Version: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+ pIt = pNode->FirstChild("url");
+ if (pIt)
+ {
+ sBoxInfo.image_url = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Image Url: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+ pIt = pNode->FirstChild("comment");
+ if (pIt)
+ {
+ sBoxInfo.image_comment = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Image Comment: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+ pIt = pNode->FirstChild("catalog");
+ if (pIt)
+ {
+ sBoxInfo.image_catalog = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Image Catalog: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+ }
+ pNode = pRootElement->FirstChild("firmware");
+ if (pNode)
+ {
+ sBoxInfo.firmware = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Firmware: %s", __FUNCTION__, pNode->FirstChild()->Value());
+ }
+ pNode = pRootElement->FirstChild("fpfirmware");
+ if (pNode)
+ {
+ sBoxInfo.fpfirmware = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - FP Firmware: %s", __FUNCTION__, pNode->FirstChild()->Value());
+ }
+ pNode = pRootElement->FirstChild("webinterface");
+ if (pNode)
+ {
+ sBoxInfo.webinterface = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Web Interface: %s", __FUNCTION__, pNode->FirstChild()->Value());
+ }
+ pNode = pRootElement->FirstChild("model");
+ if (pNode)
+ {
+ sBoxInfo.model = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Model: %s", __FUNCTION__, pNode->FirstChild()->Value());
+ }
+ pNode = pRootElement->FirstChild("manufacturer");
+ if (pNode)
+ {
+ sBoxInfo.manufacturer = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Manufacturer: %s", __FUNCTION__, pNode->FirstChild()->Value());
+ }
+ pNode = pRootElement->FirstChild("processor");
+ if (pNode)
+ {
+ sBoxInfo.processor = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Processor: %s", __FUNCTION__, pNode->FirstChild()->Value());
+ }
+ pNode = pRootElement->FirstChild("usbstick");
+ if (pNode)
+ {
+ sBoxInfo.usbstick = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - USB Stick: %s", __FUNCTION__, pNode->FirstChild()->Value());
+ }
+ pNode = pRootElement->FirstChild("disk");
+ if (pNode)
+ {
+ sBoxInfo.disk = pNode->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Disk: %s", __FUNCTION__, pNode->FirstChild()->Value());
+ }
+ return true;
+ }
+ return false;
+}
+bool CTuxBoxUtil::ServiceEPG(TiXmlElement *pRootElement)
+{
+ TiXmlNode *pNode = NULL;
+ TiXmlNode *pIt = NULL;
+
+ if(pRootElement)
+ {
+ CLog::Log(LOGDEBUG, "%s - Service EPG", __FUNCTION__);
+ pNode = pRootElement->FirstChild("service");
+ if (pNode)
+ {
+ CLog::Log(LOGDEBUG, "%s - Service", __FUNCTION__);
+ pIt = pNode->FirstChild("reference");
+ if (pIt)
+ {
+ sServiceEPG.service_reference = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Service Reference: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+ pIt = pNode->FirstChild("name");
+ if (pIt)
+ {
+ sServiceEPG.service_name = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Service Name: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+ }
+ //Todo there is more then 1 event! Create a Event List!
+ pNode = pRootElement->FirstChild("event");
+ if (pNode)
+ {
+ CLog::Log(LOGDEBUG, "%s - Event", __FUNCTION__);
+ pIt = pNode->FirstChild("date");
+ if (pIt)
+ {
+ sServiceEPG.date = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Date: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+ pIt = pNode->FirstChild("time");
+ if (pIt)
+ {
+ sServiceEPG.time = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Time: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+ pIt = pNode->FirstChild("duration");
+ if (pIt)
+ {
+ sServiceEPG.duration = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Duration: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+ pIt = pNode->FirstChild("descritption");
+ if (pIt)
+ {
+ sServiceEPG.descritption = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Descritption: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+ pIt = pNode->FirstChild("genre");
+ if (pIt)
+ {
+ sServiceEPG.genre = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Genre: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+ pIt = pNode->FirstChild("genrecategory");
+ if (pIt)
+ {
+ sServiceEPG.genrecategory = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Genrecategory: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+ pIt = pNode->FirstChild("start");
+ if (pIt)
+ {
+ sServiceEPG.start = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Start: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+ pIt = pNode->FirstChild("details");
+ if (pIt)
+ {
+ sServiceEPG.details = pIt->FirstChild()->Value();
+ CLog::Log(LOGDEBUG, "%s - Details: %s", __FUNCTION__, pIt->FirstChild()->Value());
+ }
+ }
+ return true;
+ }
+ return false;
+}
+//PopUp and request the AudioChannel
+//No PopUp: On 1x detected AudioChannel
+bool CTuxBoxUtil::GetGUIRequestedAudioChannel(AUDIOCHANNEL& sRequestedAC)
+{
+ sRequestedAC = sCurSrvData.audio_channels[0];
+
+ // Audio Selection is Disabled! Return false to use default values!
+ if(!g_advancedSettings.m_bTuxBoxAudioChannelSelection)
+ {
+ CLog::Log(LOGDEBUG, "%s - Audio Channel Selection is Disabled! Returning False to use the default values!", __FUNCTION__);
+ return false;
+ }
+
+ // We have only one Audio Channel return false to use default values!
+ if(sCurSrvData.audio_channels.size() == 1)
+ return false;
+
+ // popup the context menu
+ CContextButtons buttons;
+
+ // add the needed Audio buttons
+ for (unsigned int i = 0; i < sCurSrvData.audio_channels.size(); ++i)
+ buttons.Add(i, sCurSrvData.audio_channels[i].name);
+
+ int channel = CGUIDialogContextMenu::ShowAndGetChoice(buttons);
+ if (channel >= 0)
+ {
+ sRequestedAC = sCurSrvData.audio_channels[channel];
+ sCurSrvData.requested_audio_channel = channel;
+ CLog::Log(LOGDEBUG, "%s - Audio channel %s requested.", __FUNCTION__, sRequestedAC.name.c_str());
+ return true;
+ }
+ return false;
+}
+bool CTuxBoxUtil::GetRequestedAudioChannel(AUDIOCHANNEL& sRequestedAC) const
+{
+ sRequestedAC = sCurSrvData.audio_channels[sCurSrvData.requested_audio_channel];
+
+ return true;
+}
+bool CTuxBoxUtil::GetVideoSubChannels(std::string& strVideoSubChannelName, std::string& strVideoSubChannelPid)
+{
+ // no video sub channel return false!
+ if(vVideoSubChannel.name.size() <= 0 || vVideoSubChannel.reference.size() <= 0)
+ return false;
+
+ // IsPlaying, Stop it..
+ if(g_application.m_pPlayer->IsPlaying())
+ CApplicationMessenger::Get().MediaStop();
+
+ // popup the context menu
+ CContextButtons buttons;
+
+ // add the needed Audio buttons
+ for (unsigned int i = 0; i < vVideoSubChannel.name.size(); ++i)
+ buttons.Add(i, vVideoSubChannel.name[i]);
+
+ // get selected Video Sub Channel name and reference zap
+ int channel = CGUIDialogContextMenu::ShowAndGetChoice(buttons);
+ if (channel >= 0)
+ {
+ strVideoSubChannelName = vVideoSubChannel.name[channel];
+ strVideoSubChannelPid = vVideoSubChannel.reference[channel];
+ vVideoSubChannel.name.clear();
+ vVideoSubChannel.reference.clear();
+ vVideoSubChannel.selected.clear();
+ return true;
+ }
+ return false;
+}
+//Input: Service Name (Channel Namne)
+//Output: picon url (on ERROR the default icon path will be returned)
+std::string CTuxBoxUtil::GetPicon(std::string strServiceName)
+{
+ if(!g_advancedSettings.m_bTuxBoxPictureIcon)
+ {
+ CLog::Log(LOGDEBUG, "%s PictureIcon Detection is Disabled! Using default icon", __FUNCTION__);
+ return "";
+ }
+ if (strServiceName.empty())
+ {
+ CLog::Log(LOGDEBUG, "%s Service Name is Empty! Can not detect a PictureIcon. Using default icon!", __FUNCTION__);
+ return "";
+ }
+ else
+ {
+ std::string piconXML, piconPath, defaultPng;
+ piconPath = "special://xbmc/userdata/PictureIcon/Picon/";
+ defaultPng = piconPath+"tuxbox.png";
+ piconXML = "special://xbmc/userdata/PictureIcon/picon.xml";
+ CXBMCTinyXML piconDoc;
+
+ if (!CFile::Exists(piconXML))
+ return defaultPng;
+
+ if (!piconDoc.LoadFile(piconXML))
+ {
+ CLog::Log(LOGERROR, "Error loading %s, Line %d\n%s", piconXML.c_str(), piconDoc.ErrorRow(), piconDoc.ErrorDesc());
+ return defaultPng;
+ }
+
+ TiXmlElement *pRootElement = piconDoc.RootElement();
+ if (!pRootElement || strcmpi(pRootElement->Value(),"picon") != 0)
+ {
+ CLog::Log(LOGERROR, "Error loading %s, no <picon> node", piconXML.c_str());
+ return defaultPng;
+ }
+
+ TiXmlElement* pServices = pRootElement->FirstChildElement("services");
+ TiXmlElement* pService;
+ pService = pServices->FirstChildElement("service");
+ while(pService)
+ {
+ std::string strName = XMLUtils::GetAttribute(pService, "name");
+ std::string strPng = XMLUtils::GetAttribute(pService, "png");
+
+ if(strName == strServiceName)
+ {
+ strPng = piconPath + strPng;
+ StringUtils::ToLower(strPng);
+ CLog::Log(LOGDEBUG, "%s %s: Path is: %s", __FUNCTION__,strServiceName.c_str(), strPng.c_str());
+ return strPng;
+ }
+ pService = pService->NextSiblingElement("service");
+ }
+ return defaultPng;
+ }
+}
+
+// iMODE: 0 = TV, 1 = Radio, 2 = Data, 3 = Movies, 4 = Root
+// SUBMODE: 0 = n/a, 1 = All, 2 = Satellites, 2 = Providers, 4 = Bouquets
+std::string CTuxBoxUtil::GetSubMode(int iMode, std::string& strXMLRootString, std::string& strXMLChildString)
+{
+ //Todo: add a setting: "Don't Use Request mode" to advanced.xml
+
+ // MODE: 0 = TV, 1 = Radio, 2 = Data, 3 = Movies, 4 = Root
+ // SUBMODE: 0 = n/a, 1 = All, 2 = Satellites, 2 = Providers, 4 = Bouquets
+ // Default Submode
+ std::string strSubMode;
+
+ if(iMode <0 || iMode >4)
+ {
+ strSubMode = StringUtils::Format("xml/services?mode=0&submode=4");
+ strXMLRootString = StringUtils::Format("bouquets");
+ strXMLChildString = StringUtils::Format("bouquet");
+ return strSubMode;
+ }
+
+ // popup the context menu
+
+ // FIXME: Localize these
+ CContextButtons choices;
+ choices.Add(1, "All");
+ choices.Add(2, "Satellites");
+ choices.Add(3, "Providers");
+ choices.Add(4, "Bouquets");
+
+ int iSubMode = CGUIDialogContextMenu::ShowAndGetChoice(choices);
+ if (iSubMode == 1)
+ {
+ strXMLRootString = StringUtils::Format("services");
+ strXMLChildString = StringUtils::Format("service");
+ }
+ else if (iSubMode == 2)
+ {
+ strXMLRootString = StringUtils::Format("satellites");
+ strXMLChildString = StringUtils::Format("satellite");
+ }
+ else if (iSubMode == 3)
+ {
+ strXMLRootString = StringUtils::Format("providers");
+ strXMLChildString = StringUtils::Format("provider");
+ }
+ else // if (iSubMode == 4 || iSubMode < 0)
+ {
+ iSubMode = 4;
+ strXMLRootString = StringUtils::Format("bouquets");
+ strXMLChildString = StringUtils::Format("bouquet");
+ }
+ strSubMode = StringUtils::Format("xml/services?mode=%i&submode=%i",iMode,iSubMode);
+ return strSubMode;
+}
+//Input: url/path of share/item file/folder
+//Output: the detected submode root and child string
+std::string CTuxBoxUtil::DetectSubMode(std::string strSubMode, std::string& strXMLRootString, std::string& strXMLChildString)
+{
+ //strSubMode = "xml/services?mode=0&submode=1"
+ std::string strFilter;
+ size_t ipointMode = strSubMode.find("?mode=");
+ size_t ipointSubMode = strSubMode.find("&submode=");
+ if (ipointMode != std::string::npos)
+ strFilter.assign(1, strSubMode.at(ipointMode + 6));
+
+ if (ipointSubMode != std::string::npos)
+ {
+ char v = strSubMode.at(ipointSubMode + 9);
+ if(v == '1')
+ {
+ strXMLRootString = "unknowns";
+ strXMLChildString = "unknown";
+ }
+ else if(v == '2')
+ {
+ strXMLRootString = "satellites";
+ strXMLChildString = "satellite";
+ }
+ else if(v == '3')
+ {
+ strXMLRootString = "providers";
+ strXMLChildString = "provider";
+ }
+ else if(v == '4')
+ {
+ strXMLRootString = "bouquets";
+ strXMLChildString = "bouquet";
+ }
+
+ }
+ return strFilter;
+}