Merge pull request #5095 from koying/fixdroidappcrash
[vuplus_xbmc] / xbmc / filesystem / SlingboxFile.cpp
1 /*
2  *      Copyright (C) 2011-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "FileItem.h"
22 #include "SlingboxFile.h"
23 #include "filesystem/File.h"
24 #include "lib/SlingboxLib/SlingboxLib.h"
25 #include "profiles/ProfilesManager.h"
26 #include "utils/log.h"
27 #include "utils/XMLUtils.h"
28 #include "utils/StringUtils.h"
29 #include "URL.h"
30
31 using namespace XFILE;
32 using namespace std;
33
34 CSlingboxFile::CSlingboxFile()
35 {
36   // Create the Slingbox object
37   m_pSlingbox = new CSlingbox();
38 }
39
40 CSlingboxFile::~CSlingboxFile()
41 {
42   // Destroy the Slingbox object
43   delete m_pSlingbox;
44 }
45
46 bool CSlingboxFile::Open(const CURL& url)
47 {
48   // Setup the IP/hostname and port (setup default port if none specified)
49   unsigned int uiPort;
50   if (url.HasPort())
51     uiPort = (unsigned int)url.GetPort();
52   else
53     uiPort = 5001;
54   m_pSlingbox->SetAddress(url.GetHostName(), uiPort);
55
56   // Prepare to connect to the Slingbox
57   bool bAdmin;
58   if (StringUtils::EqualsNoCase(url.GetUserName(), "administrator"))
59     bAdmin = true;
60   else if (StringUtils::EqualsNoCase(url.GetUserName(), "viewer"))
61     bAdmin = false;
62   else
63   {
64     CLog::Log(LOGERROR, "%s - Invalid or no username specified for Slingbox: %s",
65       __FUNCTION__, url.GetHostName().c_str());
66     return false;
67   }
68
69   // Connect to the Slingbox
70   if (m_pSlingbox->Connect(bAdmin, url.GetPassWord()))
71   {
72     CLog::Log(LOGDEBUG, "%s - Successfully connected to Slingbox: %s",
73       __FUNCTION__, url.GetHostName().c_str());
74   }
75   else
76   {
77     CLog::Log(LOGERROR, "%s - Error connecting to Slingbox: %s",
78       __FUNCTION__, url.GetHostName().c_str());
79     return false;
80   }
81
82   // Initialize the stream
83   if (m_pSlingbox->InitializeStream())
84   {
85     CLog::Log(LOGDEBUG, "%s - Successfully initialized stream on Slingbox: %s",
86       __FUNCTION__, url.GetHostName().c_str());
87   }
88   else
89   {
90     CLog::Log(LOGERROR, "%s - Error initializing stream on Slingbox: %s",
91       __FUNCTION__, url.GetHostName().c_str());
92     return false;
93   }
94
95   // Set correct input
96   if (url.GetFileNameWithoutPath() != "")
97   {
98     if (m_pSlingbox->SetInput(atoi(url.GetFileNameWithoutPath())))
99       CLog::Log(LOGDEBUG, "%s - Successfully requested change to input %i on Slingbox: %s",
100         __FUNCTION__, atoi(url.GetFileNameWithoutPath()), url.GetHostName().c_str());
101     else
102       CLog::Log(LOGERROR, "%s - Error requesting change to input %i on Slingbox: %s",
103         __FUNCTION__, atoi(url.GetFileNameWithoutPath()), url.GetHostName().c_str());
104   }
105
106   // Load the video settings
107   LoadSettings(url.GetHostName());
108
109   // Setup video options  
110   if (m_pSlingbox->StreamSettings((CSlingbox::Resolution)m_sSlingboxSettings.iVideoResolution,
111     m_sSlingboxSettings.iVideoBitrate, m_sSlingboxSettings.iVideoFramerate,
112     m_sSlingboxSettings.iVideoSmoothing, m_sSlingboxSettings.iAudioBitrate,
113     m_sSlingboxSettings.iIFrameInterval))
114   {
115     CLog::Log(LOGDEBUG, "%s - Successfully set stream options (resolution: %ix%i; "
116       "video bitrate: %i kbit/s; fps: %i; smoothing: %i%%; audio bitrate %i kbit/s; "
117       "I frame interval: %i) on Slingbox: %s", __FUNCTION__,
118       m_sSlingboxSettings.iVideoWidth, m_sSlingboxSettings.iVideoHeight,
119       m_sSlingboxSettings.iVideoBitrate, m_sSlingboxSettings.iVideoFramerate,
120       m_sSlingboxSettings.iVideoSmoothing, m_sSlingboxSettings.iAudioBitrate,
121       m_sSlingboxSettings.iIFrameInterval, url.GetHostName().c_str());
122   }
123   else
124   {
125     CLog::Log(LOGERROR, "%s - Error setting stream options on Slingbox: %s",
126       __FUNCTION__, url.GetHostName().c_str());
127   }
128
129   // Start the stream
130   if (m_pSlingbox->StartStream())
131   {
132     CLog::Log(LOGDEBUG, "%s - Successfully started stream on Slingbox: %s",
133       __FUNCTION__, url.GetHostName().c_str());
134   }
135   else
136   {
137     CLog::Log(LOGERROR, "%s - Error starting stream on Slingbox: %s",
138       __FUNCTION__, url.GetHostName().c_str());
139     return false;
140   }
141
142   // Check for correct input
143   if (url.GetFileNameWithoutPath() != "")
144   {
145     if (m_pSlingbox->GetInput() == -1)
146       CLog::Log(LOGDEBUG, "%s - Unable to confirm change to input %i on Slingbox: %s",
147         __FUNCTION__, atoi(url.GetFileNameWithoutPath()), url.GetHostName().c_str());
148     else if (m_pSlingbox->GetInput() == atoi(url.GetFileNameWithoutPath()))
149       CLog::Log(LOGDEBUG, "%s - Comfirmed change to input %i on Slingbox: %s",
150         __FUNCTION__, atoi(url.GetFileNameWithoutPath()), url.GetHostName().c_str());
151     else
152       CLog::Log(LOGERROR, "%s - Error changing to input %i on Slingbox: %s",
153         __FUNCTION__, atoi(url.GetFileNameWithoutPath()), url.GetHostName().c_str());
154   }
155
156   return true;
157 }
158
159 unsigned int CSlingboxFile::Read(void * pBuffer, int64_t iSize)
160 {
161   // Read the data and check for any errors
162   int iRead = m_pSlingbox->ReadStream(pBuffer, (unsigned int)iSize);
163   if (iRead < 0)
164   {
165     CLog::Log(LOGERROR, "%s - Error reading stream from Slingbox: %s", __FUNCTION__,
166       m_sSlingboxSettings.strHostname.c_str());
167     return 0;
168   }
169
170   return iRead;
171 }
172
173 void CSlingboxFile::Close()
174 {
175   // Stop the stream
176   if (m_pSlingbox->StopStream())
177     CLog::Log(LOGDEBUG, "%s - Successfully stopped stream on Slingbox: %s", __FUNCTION__,
178     m_sSlingboxSettings.strHostname.c_str());
179   else
180     CLog::Log(LOGERROR, "%s - Error stopping stream on Slingbox: %s", __FUNCTION__,
181     m_sSlingboxSettings.strHostname.c_str());
182
183   // Disconnect from the Slingbox
184   if (m_pSlingbox->Disconnect())
185     CLog::Log(LOGDEBUG, "%s - Successfully disconnected from Slingbox: %s", __FUNCTION__,
186     m_sSlingboxSettings.strHostname.c_str());
187   else
188     CLog::Log(LOGERROR, "%s - Error disconnecting from Slingbox: %s", __FUNCTION__,
189     m_sSlingboxSettings.strHostname.c_str());
190 }
191
192 bool CSlingboxFile::SkipNext()
193 {
194   return m_pSlingbox->IsConnected();
195 }
196
197 bool CSlingboxFile::NextChannel(bool bPreview /* = false */)
198 {
199   // Prepare variables
200   bool bSuccess = true;
201   int iPrevChannel = m_pSlingbox->GetChannel();
202
203   // Stop the stream
204   if (m_pSlingbox->StopStream())
205   {
206     CLog::Log(LOGDEBUG, "%s - Successfully stopped stream before channel change request on "
207       "Slingbox: %s", __FUNCTION__, m_sSlingboxSettings.strHostname.c_str());
208   }
209   else
210   {
211     CLog::Log(LOGERROR, "%s - Error stopping stream before channel change request on "
212       "Slingbox: %s", __FUNCTION__, m_sSlingboxSettings.strHostname.c_str());
213     bSuccess = false;
214   }
215
216   // Figure out which method to use
217   if (m_sSlingboxSettings.uiCodeChannelUp == 0)
218   {
219     // Change the channel
220     if (m_pSlingbox->ChannelUp())
221     {
222       CLog::Log(LOGDEBUG, "%s - Successfully requested channel change on Slingbox: %s",
223         __FUNCTION__, m_sSlingboxSettings.strHostname.c_str());
224
225       if (m_pSlingbox->GetChannel() == -1)
226       {
227         CLog::Log(LOGDEBUG, "%s - Unable to confirm channel change on Slingbox: %s",
228           __FUNCTION__, m_sSlingboxSettings.strHostname.c_str());
229       }
230       else if (m_pSlingbox->GetChannel() != iPrevChannel)
231       {
232         CLog::Log(LOGDEBUG, "%s - Confirmed change to channel %i on Slingbox: %s",
233           __FUNCTION__, m_pSlingbox->GetChannel(), m_sSlingboxSettings.strHostname.c_str());
234       }
235       else
236       {
237         CLog::Log(LOGERROR, "%s - Error changing channel on Slingbox: %s",
238           __FUNCTION__, m_sSlingboxSettings.strHostname.c_str());
239         bSuccess = false;
240       }
241     }
242     else
243     {
244       CLog::Log(LOGERROR, "%s - Error requesting channel change on Slingbox: %s",
245         __FUNCTION__, m_sSlingboxSettings.strHostname.c_str());
246       bSuccess = false;
247     }
248   }
249   else
250   {
251     // Change the channel using IR command
252     if (m_pSlingbox->SendIRCommand(m_sSlingboxSettings.uiCodeChannelUp))
253     {
254       CLog::Log(LOGDEBUG, "%s - Successfully sent IR command (code: 0x%.2X) from "
255         "Slingbox: %s", __FUNCTION__, m_sSlingboxSettings.uiCodeChannelUp,
256         m_sSlingboxSettings.strHostname.c_str());
257     }
258     else
259     {
260       CLog::Log(LOGERROR, "%s - Error sending IR command (code: 0x%.2X) from "
261         "Slingbox: %s", __FUNCTION__, m_sSlingboxSettings.uiCodeChannelUp,
262         m_sSlingboxSettings.strHostname.c_str());
263       bSuccess = false;
264     }
265   }
266
267   // Start the stream again
268   if (m_pSlingbox->StartStream())
269   {
270     CLog::Log(LOGDEBUG, "%s - Successfully started stream after channel change request on "
271       "Slingbox: %s", __FUNCTION__, m_sSlingboxSettings.strHostname.c_str());
272   }
273   else
274   {
275     CLog::Log(LOGERROR, "%s - Error starting stream after channel change request on "
276       "Slingbox: %s", __FUNCTION__, m_sSlingboxSettings.strHostname.c_str());
277     bSuccess = false;
278   }
279
280   return bSuccess;
281 }
282
283 bool CSlingboxFile::PrevChannel(bool bPreview /* = false */)
284 {
285   // Prepare variables
286   bool bSuccess = true;
287   int iPrevChannel = m_pSlingbox->GetChannel();
288
289   // Stop the stream
290   if (m_pSlingbox->StopStream())
291   {
292     CLog::Log(LOGDEBUG, "%s - Successfully stopped stream before channel change request on "
293       "Slingbox: %s", __FUNCTION__, m_sSlingboxSettings.strHostname.c_str());
294   }
295   else
296   {
297     CLog::Log(LOGERROR, "%s - Error stopping stream before channel change request on "
298       "Slingbox: %s", __FUNCTION__, m_sSlingboxSettings.strHostname.c_str());
299     bSuccess = false;
300   }
301
302   // Figure out which method to use
303   if (m_sSlingboxSettings.uiCodeChannelDown == 0)
304   {
305     // Change the channel
306     if (m_pSlingbox->ChannelDown())
307     {
308       CLog::Log(LOGDEBUG, "%s - Successfully requested channel change on Slingbox: %s",
309         __FUNCTION__, m_sSlingboxSettings.strHostname.c_str());
310
311       if (m_pSlingbox->GetChannel() == -1)
312       {
313         CLog::Log(LOGDEBUG, "%s - Unable to confirm channel change on Slingbox: %s",
314           __FUNCTION__, m_sSlingboxSettings.strHostname.c_str());
315       }
316       else if (m_pSlingbox->GetChannel() != iPrevChannel)
317       {
318         CLog::Log(LOGDEBUG, "%s - Confirmed change to channel %i on Slingbox: %s",
319           __FUNCTION__, m_pSlingbox->GetChannel(), m_sSlingboxSettings.strHostname.c_str());
320       }
321       else
322       {
323         CLog::Log(LOGERROR, "%s - Error changing channel on Slingbox: %s",
324           __FUNCTION__, m_sSlingboxSettings.strHostname.c_str());
325         bSuccess = false;
326       }
327     }
328     else
329     {
330       CLog::Log(LOGERROR, "%s - Error requesting channel change on Slingbox: %s",
331         __FUNCTION__, m_sSlingboxSettings.strHostname.c_str());
332       bSuccess = false;
333     }
334   }
335   else
336   {
337     // Change the channel using IR command
338     if (m_pSlingbox->SendIRCommand(m_sSlingboxSettings.uiCodeChannelDown))
339     {
340       CLog::Log(LOGDEBUG, "%s - Successfully sent IR command (code: 0x%.2X) from "
341         "Slingbox: %s", __FUNCTION__, m_sSlingboxSettings.uiCodeChannelDown,
342         m_sSlingboxSettings.strHostname.c_str());
343     }
344     else
345     {
346       CLog::Log(LOGERROR, "%s - Error sending IR command (code: 0x%.2X) from "
347         "Slingbox: %s", __FUNCTION__, m_sSlingboxSettings.uiCodeChannelDown,
348         m_sSlingboxSettings.strHostname.c_str());
349       bSuccess = false;
350     }
351   }    
352
353   // Start the stream again
354   if (m_pSlingbox->StartStream())
355   {
356     CLog::Log(LOGDEBUG, "%s - Successfully started stream after channel change request on "
357       "Slingbox: %s", __FUNCTION__, m_sSlingboxSettings.strHostname.c_str());
358   }
359   else
360   {
361     CLog::Log(LOGERROR, "%s - Error starting Slingbox stream after channel change request on "
362       "Slingbox: %s", __FUNCTION__, m_sSlingboxSettings.strHostname.c_str());
363     bSuccess = false;
364   }
365
366   return bSuccess;
367 }
368
369 bool CSlingboxFile::SelectChannel(unsigned int uiChannel)
370 {
371   // Check if a channel change is required
372   if (m_pSlingbox->GetChannel() == (int)uiChannel)
373     return false;
374
375   // Prepare variables
376   bool bSuccess = true;
377
378   // Stop the stream
379   if (m_pSlingbox->StopStream())
380   {
381     CLog::Log(LOGDEBUG, "%s - Successfully stopped stream before channel change request on "
382       "Slingbox: %s", __FUNCTION__, m_sSlingboxSettings.strHostname.c_str());
383   }
384   else
385   {
386     CLog::Log(LOGERROR, "%s - Error stopping stream before channel change request on "
387       "Slingbox: %s", __FUNCTION__, m_sSlingboxSettings.strHostname.c_str());
388     bSuccess = false;
389   }
390
391   // Figure out which method to use
392   unsigned int uiButtonsWithCode = 0;
393   for (unsigned int i = 0; i < 10; i++)
394   {
395     if (m_sSlingboxSettings.uiCodeNumber[i] != 0)
396       uiButtonsWithCode++;
397   }
398   if (uiButtonsWithCode == 0)
399   {
400     // Change the channel
401     if (m_pSlingbox->SetChannel(uiChannel))
402     {
403       CLog::Log(LOGDEBUG, "%s - Successfully requested change to channel %i on Slingbox: %s",
404         __FUNCTION__, uiChannel, m_sSlingboxSettings.strHostname.c_str());
405
406       if (m_pSlingbox->GetChannel() == -1)
407       {
408         CLog::Log(LOGDEBUG, "%s - Unable to confirm change to channel %i on Slingbox: %s",
409           __FUNCTION__, uiChannel, m_sSlingboxSettings.strHostname.c_str());
410       }
411       else if (m_pSlingbox->GetChannel() == (int)uiChannel)
412       {
413         CLog::Log(LOGDEBUG, "%s - Confirmed change to channel %i on Slingbox: %s",
414           __FUNCTION__, uiChannel, m_sSlingboxSettings.strHostname.c_str());
415       }
416       else
417       {
418         CLog::Log(LOGERROR, "%s - Error changing to channel %i on Slingbox: %s",
419           __FUNCTION__, uiChannel, m_sSlingboxSettings.strHostname.c_str());
420         bSuccess = false;
421       }
422     }
423     else
424     {
425       CLog::Log(LOGERROR, "%s - Error requesting change to channel %i on Slingbox: %s",
426         __FUNCTION__, uiChannel, m_sSlingboxSettings.strHostname.c_str());
427       bSuccess = false;
428     }
429   }
430   else if (uiButtonsWithCode == 10)
431   {
432     // Prepare variables
433     CStdString strDigits = StringUtils::Format("%u", uiChannel);
434     size_t uiNumberOfDigits = strDigits.size();
435
436     // Change the channel using IR commands
437     for (size_t i = 0; i < uiNumberOfDigits; i++)
438     {
439       if (m_pSlingbox->SendIRCommand(m_sSlingboxSettings.uiCodeNumber[strDigits[i] - '0']))
440       {
441         CLog::Log(LOGDEBUG, "%s - Successfully sent IR command (code: 0x%.2X) from "
442           "Slingbox: %s", __FUNCTION__, m_sSlingboxSettings.uiCodeNumber[strDigits[i] - '0'],
443           m_sSlingboxSettings.strHostname.c_str());
444       }
445       else
446       {
447         CLog::Log(LOGDEBUG, "%s - Error sending IR command (code: 0x%.2X) from "
448           "Slingbox: %s", __FUNCTION__, m_sSlingboxSettings.uiCodeNumber[strDigits[i] - '0'],
449           m_sSlingboxSettings.strHostname.c_str());
450         bSuccess = false;
451       }
452     }
453   }
454   else
455   {
456     CLog::Log(LOGERROR, "%s - Error requesting change to channel %i on Slingbox due to one or more "
457       "missing button codes from advancedsettings.xml for Slingbox: %s", __FUNCTION__, uiChannel,
458       m_sSlingboxSettings.strHostname.c_str());
459     bSuccess = false;
460   }
461
462   // Start the stream again
463   if (m_pSlingbox->StartStream())
464   {
465     CLog::Log(LOGDEBUG, "%s - Successfully started stream after channel change request on "
466       "Slingbox: %s", __FUNCTION__, m_sSlingboxSettings.strHostname.c_str());
467   }
468   else
469   {
470     CLog::Log(LOGERROR, "%s - Error starting stream after channel change request on "
471       "Slingbox: %s", __FUNCTION__, m_sSlingboxSettings.strHostname.c_str());
472     bSuccess = false;
473   }
474
475   return bSuccess;
476 }
477
478 void CSlingboxFile::LoadSettings(const CStdString& strHostname)
479 {
480   // Load default settings
481   m_sSlingboxSettings.strHostname = strHostname;
482   m_sSlingboxSettings.iVideoWidth = 320;
483   m_sSlingboxSettings.iVideoHeight = 240;
484   m_sSlingboxSettings.iVideoResolution = (int)CSlingbox::RESOLUTION320X240;
485   m_sSlingboxSettings.iVideoBitrate = 704;
486   m_sSlingboxSettings.iVideoFramerate = 30;
487   m_sSlingboxSettings.iVideoSmoothing = 50;
488   m_sSlingboxSettings.iAudioBitrate = 64;
489   m_sSlingboxSettings.iIFrameInterval = 10;
490   m_sSlingboxSettings.uiCodeChannelUp = 0;
491   m_sSlingboxSettings.uiCodeChannelDown = 0;
492   for (unsigned int i = 0; i < 10; i++)
493     m_sSlingboxSettings.uiCodeNumber[i] = 0;
494
495   // Check if a SlingboxSettings.xml file exists
496   CStdString slingboxXMLFile = CProfilesManager::Get().GetUserDataItem("SlingboxSettings.xml");
497   if (!CFile::Exists(slingboxXMLFile))
498   {
499     CLog::Log(LOGNOTICE, "No SlingboxSettings.xml file (%s) found - using default settings",
500       slingboxXMLFile.c_str());
501     return;
502   }
503
504   // Load the XML file
505   CXBMCTinyXML slingboxXML;
506   if (!slingboxXML.LoadFile(slingboxXMLFile))
507   {
508     CLog::Log(LOGERROR, "%s - Error loading %s - line %d\n%s", __FUNCTION__, 
509       slingboxXMLFile.c_str(), slingboxXML.ErrorRow(), slingboxXML.ErrorDesc());
510     return;
511   }
512
513   // Check to make sure layout is correct
514   TiXmlElement * pRootElement = slingboxXML.RootElement();
515   if (!pRootElement || strcmpi(pRootElement->Value(), "slingboxsettings") != 0)
516   {
517     CLog::Log(LOGERROR, "%s - Error loading %s - no <slingboxsettings> node found",
518       __FUNCTION__, slingboxXMLFile.c_str());
519     return;
520   }
521
522   // Success so far
523   CLog::Log(LOGNOTICE, "Loaded SlingboxSettings.xml from %s", slingboxXMLFile.c_str());
524
525   // Search for the first settings that specify no hostname or match our hostname
526   TiXmlElement *pElement;
527   for (pElement = pRootElement->FirstChildElement("slingbox"); pElement;
528     pElement = pElement->NextSiblingElement("slingbox"))
529   {
530     if (pElement->Attribute("hostname") == NULL ||      
531       StringUtils::EqualsNoCase(m_sSlingboxSettings.strHostname, pElement->Attribute("hostname")))
532     {
533       // Load setting values
534       XMLUtils::GetInt(pElement, "width", m_sSlingboxSettings.iVideoWidth, 0, 640);
535       XMLUtils::GetInt(pElement, "height", m_sSlingboxSettings.iVideoHeight, 0, 480);
536       XMLUtils::GetInt(pElement, "videobitrate", m_sSlingboxSettings.iVideoBitrate, 50, 8000);
537       XMLUtils::GetInt(pElement, "framerate", m_sSlingboxSettings.iVideoFramerate, 1, 30);
538       XMLUtils::GetInt(pElement, "smoothing", m_sSlingboxSettings.iVideoSmoothing, 0, 100);
539       XMLUtils::GetInt(pElement, "audiobitrate", m_sSlingboxSettings.iAudioBitrate, 16, 96);
540       XMLUtils::GetInt(pElement, "iframeinterval", m_sSlingboxSettings.iIFrameInterval, 1, 30);
541
542       // Load any button code values
543       TiXmlElement * pCodes = pElement->FirstChildElement("buttons");
544       if (pCodes)
545       {
546         XMLUtils::GetHex(pCodes, "channelup", m_sSlingboxSettings.uiCodeChannelUp);
547         XMLUtils::GetHex(pCodes, "channeldown", m_sSlingboxSettings.uiCodeChannelDown);
548         XMLUtils::GetHex(pCodes, "zero", m_sSlingboxSettings.uiCodeNumber[0]);
549         XMLUtils::GetHex(pCodes, "one", m_sSlingboxSettings.uiCodeNumber[1]);
550         XMLUtils::GetHex(pCodes, "two", m_sSlingboxSettings.uiCodeNumber[2]);
551         XMLUtils::GetHex(pCodes, "three", m_sSlingboxSettings.uiCodeNumber[3]);
552         XMLUtils::GetHex(pCodes, "four", m_sSlingboxSettings.uiCodeNumber[4]);
553         XMLUtils::GetHex(pCodes, "five", m_sSlingboxSettings.uiCodeNumber[5]);
554         XMLUtils::GetHex(pCodes, "six", m_sSlingboxSettings.uiCodeNumber[6]);
555         XMLUtils::GetHex(pCodes, "seven", m_sSlingboxSettings.uiCodeNumber[7]);
556         XMLUtils::GetHex(pCodes, "eight", m_sSlingboxSettings.uiCodeNumber[8]);
557         XMLUtils::GetHex(pCodes, "nine", m_sSlingboxSettings.uiCodeNumber[9]);
558       }
559
560       break;
561     }
562   }
563
564   // Prepare our resolution enum mapping array
565   const struct
566   {
567     unsigned int uiWidth;
568     unsigned int uiHeight;
569     CSlingbox::Resolution eEnum;
570   } m_resolutionMap[11] = {
571     {0, 0, CSlingbox::NOVIDEO},
572     {128, 96, CSlingbox::RESOLUTION128X96},
573     {160, 120, CSlingbox::RESOLUTION160X120},
574     {176, 120, CSlingbox::RESOLUTION176X120},
575     {224, 176, CSlingbox::RESOLUTION224X176},
576     {256, 192, CSlingbox::RESOLUTION256X192},
577     {320, 240, CSlingbox::RESOLUTION320X240},
578     {352, 240, CSlingbox::RESOLUTION352X240},
579     {320, 480, CSlingbox::RESOLUTION320X480},
580     {640, 240, CSlingbox::RESOLUTION640X240},
581     {640, 480, CSlingbox::RESOLUTION640X480}
582   };
583
584   // See if the specified resolution matches something in our mapping array and
585   // setup things accordingly
586   for (unsigned int i = 0; i < 11; i++)
587   {
588     if (m_sSlingboxSettings.iVideoWidth == (int)m_resolutionMap[i].uiWidth &&
589       m_sSlingboxSettings.iVideoHeight == (int)m_resolutionMap[i].uiHeight)
590     {
591       m_sSlingboxSettings.iVideoResolution = (int)m_resolutionMap[i].eEnum;
592       return;
593     }
594   }
595
596   // If it didn't match anything setup safe defaults
597   CLog::Log(LOGERROR, "%s - Defaulting to 320x240 resolution due to invalid "
598     "resolution specified in SlingboxSettings.xml for Slingbox: %s",
599     __FUNCTION__, m_sSlingboxSettings.strHostname.c_str());
600   m_sSlingboxSettings.iVideoWidth = 320;
601   m_sSlingboxSettings.iVideoHeight = 240;
602   m_sSlingboxSettings.iVideoResolution = (int)CSlingbox::RESOLUTION320X240;
603 }