changed: Add logic to properly handle subtitles for stacked files
[vuplus_xbmc] / xbmc / addons / include / xbmc_stream_utils.hpp
1 #pragma once
2 /*
3  *      Copyright (C) 2005-2013 Team XBMC
4  *      http://xbmc.org
5  *
6  *  This Program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2, or (at your option)
9  *  any later version.
10  *
11  *  This Program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with XBMC; see the file COPYING.  If not, see
18  *  <http://www.gnu.org/licenses/>.
19  *
20  */
21
22 #include "xbmc_pvr_types.h"
23 #include <map>
24
25 namespace ADDON
26 {
27   class XbmcStreamProperties
28   {
29   public:
30     XbmcStreamProperties(void)
31     {
32       Clear();
33     }
34
35     virtual ~XbmcStreamProperties(void)
36     {
37     }
38
39     int GetStreamId(unsigned int iPhysicalId)
40     {
41       std::map<unsigned int, unsigned int>::iterator it = m_streamIndex.find(iPhysicalId);
42       if (it != m_streamIndex.end())
43         return it->second;
44       return -1;
45     }
46
47     void GetStreamData(unsigned int iPhysicalId, PVR_STREAM_PROPERTIES::PVR_STREAM* stream)
48     {
49       std::map<unsigned int, unsigned int>::iterator it = m_streamIndex.find(iPhysicalId);
50       if (it != m_streamIndex.end())
51       {
52         memcpy(stream, &m_streams.stream[it->second], sizeof(PVR_STREAM_PROPERTIES::PVR_STREAM));
53       }
54       else
55       {
56         memset(stream, 0, sizeof(PVR_STREAM_PROPERTIES::PVR_STREAM));
57         stream->iIdentifier = -1;
58         stream->iPhysicalId = iPhysicalId;
59       }
60     }
61
62     PVR_STREAM_PROPERTIES::PVR_STREAM* GetStreamById(unsigned int iPhysicalId)
63     {
64       std::map<unsigned int, unsigned int>::iterator it = m_streamIndex.find(iPhysicalId);
65       if (it != m_streamIndex.end())
66         return &m_streams.stream[it->second];
67       return NULL;
68     }
69
70     bool GetProperties(PVR_STREAM_PROPERTIES* props) const
71     {
72       props->iStreamCount = m_streams.iStreamCount;
73       for (unsigned int i = 0; i < m_streams.iStreamCount; i++)
74       {
75         props->stream[i].iPhysicalId    = m_streams.stream[i].iPhysicalId;
76         props->stream[i].iCodecType     = m_streams.stream[i].iCodecType;
77         props->stream[i].iCodecId       = m_streams.stream[i].iCodecId;
78         props->stream[i].strLanguage[0] = m_streams.stream[i].strLanguage[0];
79         props->stream[i].strLanguage[1] = m_streams.stream[i].strLanguage[1];
80         props->stream[i].strLanguage[2] = m_streams.stream[i].strLanguage[2];
81         props->stream[i].strLanguage[3] = m_streams.stream[i].strLanguage[3];
82         props->stream[i].iIdentifier    = m_streams.stream[i].iIdentifier;
83         props->stream[i].iFPSScale      = m_streams.stream[i].iFPSScale;
84         props->stream[i].iFPSRate       = m_streams.stream[i].iFPSRate;
85         props->stream[i].iHeight        = m_streams.stream[i].iHeight;
86         props->stream[i].iWidth         = m_streams.stream[i].iWidth;
87         props->stream[i].fAspect        = m_streams.stream[i].fAspect;
88         props->stream[i].iChannels      = m_streams.stream[i].iChannels;
89         props->stream[i].iSampleRate    = m_streams.stream[i].iSampleRate;
90         props->stream[i].iBlockAlign    = m_streams.stream[i].iBlockAlign;
91         props->stream[i].iBitRate       = m_streams.stream[i].iBitRate;
92         props->stream[i].iBitsPerSample = m_streams.stream[i].iBitsPerSample;
93       }
94
95       return (props->iStreamCount > 0);
96     }
97
98     void Clear(void)
99     {
100       memset(&m_streams, 0, sizeof(PVR_STREAM_PROPERTIES));
101       for (unsigned int i = 0; i < PVR_STREAM_MAX_STREAMS; i++)
102         m_streams.stream[i].iCodecType = XBMC_CODEC_TYPE_UNKNOWN;
103     }
104
105     unsigned int NextFreeIndex(void)
106     {
107       unsigned int i;
108       for (i = 0; i < PVR_STREAM_MAX_STREAMS; i++)
109       {
110         if (m_streams.stream[i].iCodecType == XBMC_CODEC_TYPE_UNKNOWN)
111           break;
112       }
113       return i;
114     }
115
116     static std::map<unsigned int, unsigned int> CreateIndex(PVR_STREAM_PROPERTIES streams)
117     {
118       std::map<unsigned int, unsigned int> retval;
119       for (unsigned int i = 0; i < PVR_STREAM_MAX_STREAMS && i < streams.iStreamCount; i++)
120         retval.insert(std::make_pair(streams.stream[i].iPhysicalId, i));
121       return retval;
122     }
123
124     static std::map<unsigned int, unsigned int> CreateIndex(const std::vector<PVR_STREAM_PROPERTIES::PVR_STREAM>& streams)
125     {
126       std::map<unsigned int, unsigned int> retval;
127       for (unsigned int i = 0; i < PVR_STREAM_MAX_STREAMS && i < streams.size(); i++)
128         retval.insert(std::make_pair(streams.at(i).iPhysicalId, i));
129       return retval;
130     }
131
132     static void ClearStream(PVR_STREAM_PROPERTIES::PVR_STREAM* stream)
133     {
134       memset(stream, 0, sizeof(PVR_STREAM_PROPERTIES::PVR_STREAM));
135       stream->iCodecType = XBMC_CODEC_TYPE_UNKNOWN;
136       stream->iCodecId   = XBMC_INVALID_CODEC_ID;
137     }
138
139     void UpdateStreams(const std::vector<PVR_STREAM_PROPERTIES::PVR_STREAM>& newStreams)
140     {
141       std::map<unsigned int, unsigned int> newIndex = CreateIndex(newStreams);
142
143       // delete streams we don't have in newStreams
144       std::map<unsigned int, unsigned int>::iterator ito = m_streamIndex.begin();
145       std::map<unsigned int, unsigned int>::iterator itn;
146       while (ito != m_streamIndex.end())
147       {
148         itn = newIndex.find(ito->first);
149         if (itn == newIndex.end())
150         {
151           memset(&m_streams.stream[ito->second], 0, sizeof(PVR_STREAM_PROPERTIES::PVR_STREAM));
152           m_streams.stream[ito->second].iCodecType = XBMC_CODEC_TYPE_UNKNOWN;
153           m_streams.stream[ito->second].iCodecId   = XBMC_INVALID_CODEC_ID;
154           m_streamIndex.erase(ito);
155           ito = m_streamIndex.begin();
156         }
157         else
158           ++ito;
159       }
160
161       // copy known streams
162       for (ito = m_streamIndex.begin(); ito != m_streamIndex.end(); ++ito)
163       {
164         itn = newIndex.find(ito->first);
165         memcpy(&m_streams.stream[ito->second], &newStreams.at(itn->second), sizeof(PVR_STREAM_PROPERTIES::PVR_STREAM));
166         newIndex.erase(itn);
167       }
168
169       // place video stream at pos 0
170       for (itn = newIndex.begin(); itn != newIndex.end(); ++itn)
171       {
172         if (newStreams.at(itn->second).iCodecType == XBMC_CODEC_TYPE_VIDEO)
173         {
174           m_streamIndex[itn->first] = 0;
175           memcpy(&m_streams.stream[0], &newStreams.at(itn->second), sizeof(PVR_STREAM_PROPERTIES::PVR_STREAM));
176           newIndex.erase(itn);
177           break;
178         }
179       }
180
181       // fill the gaps or append after highest index
182       while (!newIndex.empty())
183       {
184         // find first unused index
185         unsigned int i = NextFreeIndex();
186         itn = newIndex.begin();
187         m_streamIndex[itn->first] = i;
188         memcpy(&m_streams.stream[i], &newStreams.at(itn->second), sizeof(PVR_STREAM_PROPERTIES::PVR_STREAM));
189         newIndex.erase(itn);
190       }
191
192       // set streamCount
193       m_streams.iStreamCount = 0;
194       for (ito = m_streamIndex.begin(); ito != m_streamIndex.end(); ++ito)
195       {
196         if (ito->second > m_streams.iStreamCount)
197           m_streams.iStreamCount = ito->second;
198       }
199       if (!m_streamIndex.empty())
200         m_streams.iStreamCount++;
201     }
202
203     size_t Size(void) const
204     {
205       return m_streamIndex.size();
206     }
207
208     std::map<unsigned int, unsigned int> m_streamIndex;
209     PVR_STREAM_PROPERTIES                m_streams;
210   };
211 }