feab52155c21f6d56b8b158ea17fafdf3b188b49
[openblackhole/openblackhole-enigma2.git] / lib / dvb / metaparser.cpp
1 #include <lib/dvb/metaparser.h>
2 #include <lib/base/cfile.h>
3 #include <lib/base/eerror.h>
4 #include <lib/service/iservice.h>
5 #include <errno.h>
6 #include <sys/stat.h>
7
8 eDVBMetaParser::eDVBMetaParser()
9 {
10         m_time_create = 0;
11         m_data_ok = 0;
12         m_length = 0;
13         m_filesize = 0;
14         m_packet_size = 188;
15         m_scrambled = 0;
16 }
17
18 static int getctime(const std::string &basename)
19 {
20         struct stat s;
21         if (::stat(basename.c_str(), &s) == 0)
22         {
23                 return s.st_ctime;
24         }
25         return 0;
26 }
27
28 static long long fileSize(const std::string &basename)
29 {
30         long long filesize = 0;
31         char buf[8];
32         std::string splitname;
33         struct stat64 s;
34
35         /* get filesize */
36         if (!stat64(basename.c_str(), &s))
37                 filesize = (long long) s.st_size;
38         /* handling for old splitted recordings (enigma 1) */
39         int slice=1;
40         while(true)
41         {
42                 snprintf(buf, sizeof(buf), ".%03d", slice++);
43                 splitname = basename + buf;
44                 if (stat64(splitname.c_str(), &s) < 0)
45                         break;
46                 filesize += (long long) s.st_size;
47         }
48         return filesize;
49 }
50
51 int eDVBMetaParser::parseFile(const std::string &basename)
52 {
53                 /* first, try parsing the .meta file */
54         if (!parseMeta(basename))
55                 return 0;
56
57                 /* otherwise, use recordings.epl */
58         if (!parseRecordings(basename))
59                 return 0;
60         m_filesize = fileSize(basename);
61         m_time_create = getctime(basename);
62         return -1;
63 }
64
65 int eDVBMetaParser::parseMeta(const std::string &tsname)
66 {
67         /* if it's a PVR channel, recover service id. */
68         std::string filename = tsname + ".meta";
69         CFile f(filename.c_str(), "r");
70
71         if (!f)
72                 return -ENOENT;
73
74         int linecnt = 0;
75
76         m_time_create = 0;
77
78         while (1)
79         {
80                 char line[4096];
81                 if (!fgets(line, 4096, f))
82                         break;
83                 size_t len = strlen(line);
84                 if (len && line[len-1] == '\n')
85                 {
86                         --len;
87                         line[len] = 0;
88                 }
89                 if (len && line[len-1] == '\r')
90                 {
91                         --len;
92                         line[len] = 0;
93                 }
94
95                 switch (linecnt)
96                 {
97                 case 0:
98                         m_ref = eServiceReferenceDVB(line);
99                         break;
100                 case 1:
101                         m_name = line;
102                         break;
103                 case 2:
104                         m_description = line;
105                         break;
106                 case 3:
107                         m_time_create = atoi(line);
108                         if (m_time_create == 0)
109                         {
110                                 m_time_create = getctime(tsname);
111                         }
112                         break;
113                 case 4:
114                         m_tags = line;
115                         break;
116                 case 5:
117                         m_length = atoi(line);  //movielength in pts
118                         break;
119                 case 6:
120                         m_filesize = atoll(line);
121                         break;
122                 case 7:
123                         m_service_data = line;
124                         break;
125                 case 8:
126                         m_packet_size = atoi(line);
127                         if (m_packet_size <= 0)
128                         {
129                                 /* invalid value, use default */
130                                 m_packet_size = 188;
131                         }
132                         break;
133                 case 9:
134                         m_scrambled = atoi(line);
135                         break;
136                 default:
137                         break;
138                 }
139                 ++linecnt;
140         }
141         m_data_ok = 1;
142         return 0;
143 }
144
145 int eDVBMetaParser::parseRecordings(const std::string &filename)
146 {
147         std::string::size_type slash = filename.rfind('/');
148         if (slash == std::string::npos)
149                 return -1;
150
151         std::string recordings = filename.substr(0, slash) + "/recordings.epl";
152
153         CFile f(recordings.c_str(), "r");
154         if (!f)
155         {
156 //              eDebug("[eDVBMetaParser] no recordings.epl found: %s: %m", recordings.c_str());
157                 return -1;
158         }
159
160         std::string description;
161         eServiceReferenceDVB ref;
162
163 //      eDebug("[eDVBMetaParser] parsing recordings.epl..");
164
165         while (1)
166         {
167                 char line[1024];
168                 if (!fgets(line, 1024, f))
169                         break;
170
171                 size_t len = strlen(line);
172                 if (len < 2)
173                         // Lines with less than one char aren't meaningful
174                         continue;
175                 // Remove trailing \r\n
176                 --len;
177                 line[len] = 0;
178                 if (line[len-1] == '\r')
179                         line[len-1] = 0;
180
181                 if (strncmp(line, "#SERVICE: ", 10) == 0)
182                         ref = eServiceReferenceDVB(line + 10);
183                 else if (strncmp(line, "#DESCRIPTION: ", 14) == 0)
184                         description = line + 14;
185                 else if ((line[0] == '/') && (ref.path.substr(ref.path.find_last_of('/')) == filename.substr(filename.find_last_of('/'))))
186                 {
187 //                      eDebug("[eDVBMetaParser] hit! ref %s descr %s", m_ref.toString().c_str(), m_name.c_str());
188                         m_ref = ref;
189                         m_name = description;
190                         m_description = "";
191                         m_time_create = getctime(filename);
192                         m_length = 0;
193                         m_filesize = fileSize(filename);
194                         m_data_ok = 1;
195                         m_scrambled = 0;
196                         updateMeta(filename);
197                         return 0;
198                 }
199         }
200         return -1;
201 }
202
203 int eDVBMetaParser::updateMeta(const std::string &tsname)
204 {
205         /* write meta file only if we have valid data. Note that we might convert recordings.epl data to .meta, which is fine. */
206         if (!m_data_ok)
207                 return -1;
208         std::string filename = tsname + ".meta";
209         eServiceReference ref = m_ref;
210         ref.path = "";
211
212         CFile f(filename.c_str(), "w");
213         if (!f)
214                 return -ENOENT;
215
216         if (ref.getName().empty())
217         {
218                 ePtr<iServiceHandler> service_center;
219                 ePtr<iStaticServiceInformation> service_info;
220                 std::string service_name;
221                 eServiceCenter::getInstance(service_center);
222                 service_center->info(ref, service_info);
223                 service_info->getName(ref, service_name);
224                 ref.setName(service_name);
225         }
226
227         fprintf(f, "%s\n%s\n%s\n%d\n%s\n%d\n%lld\n%s\n%d\n%d\n", ref.toString().c_str(), m_name.c_str(), m_description.c_str(), m_time_create, m_tags.c_str(), m_length, m_filesize, m_service_data.c_str(), m_packet_size, m_scrambled);
228         return 0;
229 }