fixed: LINUX build errors
[xbmc:xbmc.git] / xbmc / ProgramDatabase.cpp
1 /*
2  *      Copyright (C) 2005-2008 Team XBMC
3  *      http://www.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, write to
17  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18  *  http://www.gnu.org/copyleft/gpl.html
19  *
20  */
21
22 #include "ProgramDatabase.h"
23 #include "utils/fstrcmp.h"
24 #include "Util.h"
25 #include "GUIWindowFileManager.h"
26 #include "FileItem.h"
27 #include "GUISettings.h"
28 #include "Settings.h"
29 #include "log.h"
30
31 using namespace XFILE;
32
33 #define PROGRAM_DATABASE_OLD_VERSION 0.9f
34 #define PROGRAM_DATABASE_VERSION 3
35
36 //********************************************************************************************************************************
37 CProgramDatabase::CProgramDatabase(void)
38 {
39   m_preV2version=PROGRAM_DATABASE_OLD_VERSION;
40   m_version=PROGRAM_DATABASE_VERSION;
41   m_strDatabaseFile=PROGRAM_DATABASE_NAME;
42 }
43
44 //********************************************************************************************************************************
45 CProgramDatabase::~CProgramDatabase(void)
46 {
47
48 }
49
50 //********************************************************************************************************************************
51 bool CProgramDatabase::CreateTables()
52 {
53
54   try
55   {
56     CDatabase::CreateTables();
57
58     CLog::Log(LOGINFO, "create files table");
59     m_pDS->exec("CREATE TABLE files ( idFile integer primary key, strFilename text, titleId integer, xbedescription text, iTimesPlayed integer, lastAccessed integer, iRegion integer, iSize integer)\n");
60     CLog::Log(LOGINFO, "create files index");
61     m_pDS->exec("CREATE INDEX idxFiles ON files(strFilename)");
62     CLog::Log(LOGINFO, "create files - titleid index");
63     m_pDS->exec("CREATE INDEX idxTitleIdFiles ON files(titleId)");
64   }
65   catch (...)
66   {
67     CLog::Log(LOGERROR, "programdatabase::unable to create tables:%u",
68               GetLastError());
69     return false;
70   }
71
72   return true;
73 }
74
75 bool CProgramDatabase::UpdateOldVersion(int version)
76 {
77   if (NULL == m_pDB.get()) return false;
78   if (NULL == m_pDS.get()) return false;
79   if (NULL == m_pDS2.get()) return false;
80
81   try
82   {
83   }
84   catch (...)
85   {
86     CLog::Log(LOGERROR, "Error attempting to update the database version!");
87     return false;
88   }
89   return true;
90 }
91
92 uint32_t CProgramDatabase::GetTitleId(const CStdString& strFilenameAndPath)
93 {
94   if (NULL == m_pDB.get()) return 0;
95   if (NULL == m_pDS.get()) return 0;
96
97   try
98   {
99     CStdString strSQL = FormatSQL("select * from files where files.strFileName like '%s'", strFilenameAndPath.c_str());
100     if (!m_pDS->query(strSQL.c_str()))
101       return 0;
102
103     int iRowsFound = m_pDS->num_rows();
104     if (iRowsFound == 0)
105     {
106       m_pDS->close();
107       return 0;
108     }
109     uint32_t dwTitleId = m_pDS->fv("files.TitleId").get_asLong();
110     m_pDS->close();
111     return dwTitleId;
112   }
113   catch (...)
114   {
115     CLog::Log(LOGERROR, "CProgramDatabase:GetTitleId(%s) failed", strFilenameAndPath.c_str());
116   }
117   return 0;
118 }
119
120 bool CProgramDatabase::SetTitleId(const CStdString& strFileName, uint32_t dwTitleId)
121 {
122   try
123   {
124     if (NULL == m_pDB.get()) return false;
125     if (NULL == m_pDS.get()) return false;
126
127     CStdString strSQL = FormatSQL("select * from files where files.strFileName like '%s'", strFileName.c_str());
128     if (!m_pDS->query(strSQL.c_str())) return false;
129     int iRowsFound = m_pDS->num_rows();
130     if (iRowsFound == 0)
131     {
132       m_pDS->close();
133       return false;
134     }
135     int idFile = m_pDS->fv("files.idFile").get_asLong();
136     m_pDS->close();
137
138     CLog::Log(LOGDEBUG, "CProgramDatabase::SetTitle(%s), idFile=%i, region=%u",
139               strFileName.c_str(), idFile,dwTitleId);
140
141     strSQL=FormatSQL("update files set titleId=%u where idFile=%i",
142                   dwTitleId, idFile);
143     m_pDS->exec(strSQL.c_str());
144     return true;
145   }
146   catch (...)
147   {
148     CLog::Log(LOGERROR, "CProgramDatabase:SetDescription(%s) failed", strFileName.c_str());
149   }
150
151   return false;
152 }
153
154 bool CProgramDatabase::GetXBEPathByTitleId(const uint32_t titleId, CStdString& strPathAndFilename)
155 {
156   try
157   {
158     if (NULL == m_pDB.get()) return false;
159     if (NULL == m_pDS.get()) return false;
160
161     CStdString strSQL=FormatSQL("select files.strFilename from files where files.titleId=%u", titleId);
162     m_pDS->query(strSQL.c_str());
163     if (m_pDS->num_rows() > 0)
164     {
165       strPathAndFilename = m_pDS->fv("files.strFilename").get_asString();
166       strPathAndFilename.Replace('/', '\\');
167       m_pDS->close();
168       return true;
169     }
170     m_pDS->close();
171     return false;
172   }
173   catch (...)
174   {
175     CLog::Log(LOGERROR, "CProgramDatabase::GetXBEPathByTitleId(%u) failed",
176               titleId);
177   }
178   return false;
179 }
180
181 uint32_t CProgramDatabase::GetProgramInfo(CFileItem *item)
182 {
183   uint32_t titleID = 0;
184   try
185   {
186     if (NULL == m_pDB.get()) return false;
187     if (NULL == m_pDS.get()) return false;
188
189     CStdString strSQL = FormatSQL("select xbedescription,iTimesPlayed,lastAccessed,titleId,iSize from files where strFileName like '%s'", item->m_strPath.c_str());
190     m_pDS->query(strSQL.c_str());
191     if (!m_pDS->eof())
192     { // get info - only set the label if not preformatted
193       if (!item->IsLabelPreformated())
194         item->SetLabel(m_pDS->fv("xbedescription").get_asString());
195       item->m_iprogramCount = m_pDS->fv("iTimesPlayed").get_asLong();
196       item->m_strTitle = item->GetLabel();  // is this needed?
197       item->m_dateTime = TimeStampToLocalTime(_atoi64(m_pDS->fv("lastAccessed").get_asString().c_str()));
198       item->m_dwSize = _atoi64(m_pDS->fv("iSize").get_asString().c_str());
199       titleID = m_pDS->fv("titleId").get_asLong();
200       if (item->m_dwSize == -1)
201       {
202         CStdString strPath;
203         CUtil::GetDirectory(item->m_strPath,strPath);
204         int64_t iSize = CGUIWindowFileManager::CalculateFolderSize(strPath);
205         CStdString strSQL=FormatSQL("update files set iSize=%I64u where strFileName like '%s'",iSize,item->m_strPath.c_str());
206         m_pDS->exec(strSQL.c_str());
207       }
208     }
209     m_pDS->close();
210   }
211   catch (...)
212   {
213     CLog::Log(LOGERROR, "CProgramDatabase::GetProgramInfo(%s) failed", item->m_strPath.c_str());
214   }
215   return titleID;
216 }
217
218 bool CProgramDatabase::AddProgramInfo(CFileItem *item, unsigned int titleID)
219 {
220   try
221   {
222     if (NULL == m_pDB.get()) return false;
223     if (NULL == m_pDS.get()) return false;
224
225     int iRegion = -1;
226     if (g_guiSettings.GetBool("myprograms.gameautoregion"))
227     {
228         iRegion = 0;
229     }
230     FILETIME time;
231     item->m_dateTime=CDateTime::GetCurrentDateTime();
232     item->m_dateTime.GetAsTimeStamp(time);
233
234     ULARGE_INTEGER lastAccessed;
235     lastAccessed.u.LowPart = time.dwLowDateTime; 
236     lastAccessed.u.HighPart = time.dwHighDateTime;
237
238     CStdString strPath, strParent;
239     CUtil::GetDirectory(item->m_strPath,strPath);
240     // special case - programs in root of sources
241     bool bIsShare=false;
242     CUtil::GetMatchingSource(strPath,g_settings.m_programSources,bIsShare);
243     int64_t iSize=0;
244     if (bIsShare || !item->IsDefaultXBE())
245     {
246       struct stat64 stat;
247       if (CFile::Stat(item->m_strPath,&stat) == 0)
248         iSize = stat.st_size;
249     }
250     else
251       iSize = CGUIWindowFileManager::CalculateFolderSize(strPath);
252     if (titleID == 0)
253       titleID = (unsigned int) -1;
254     CStdString strSQL=FormatSQL("insert into files (idFile, strFileName, titleId, xbedescription, iTimesPlayed, lastAccessed, iRegion, iSize) values(NULL, '%s', %u, '%s', %i, %I64u, %i, %I64u)", item->m_strPath.c_str(), titleID, item->GetLabel().c_str(), 0, lastAccessed.QuadPart, iRegion, iSize);
255     m_pDS->exec(strSQL.c_str());
256     item->m_dwSize = iSize;
257   }
258   catch (...)
259   {
260     CLog::Log(LOGERROR, "CProgramDatabase::AddProgramInfo(%s) failed", item->m_strPath.c_str());
261   }
262   return true;
263 }
264
265 FILETIME CProgramDatabase::TimeStampToLocalTime(uint64_t timeStamp )
266 {
267   FILETIME fileTime;
268   ::FileTimeToLocalFileTime( (const FILETIME *)&timeStamp, &fileTime);
269   return fileTime;
270 }
271
272 bool CProgramDatabase::IncTimesPlayed(const CStdString& strFileName)
273 {
274   try
275   {
276     if (NULL == m_pDB.get()) return false;
277     if (NULL == m_pDS.get()) return false;
278
279     CStdString strSQL = FormatSQL("select * from files where files.strFileName like '%s'", strFileName.c_str());
280     if (!m_pDS->query(strSQL.c_str())) return false;
281     int iRowsFound = m_pDS->num_rows();
282     if (iRowsFound == 0)
283     {
284       m_pDS->close();
285       return false;
286     }
287     int idFile = m_pDS->fv("files.idFile").get_asLong();
288     int iTimesPlayed = m_pDS->fv("files.iTimesPlayed").get_asLong();
289     m_pDS->close();
290
291     CLog::Log(LOGDEBUG, "CProgramDatabase::IncTimesPlayed(%s), idFile=%i, iTimesPlayed=%i",
292               strFileName.c_str(), idFile, iTimesPlayed);
293
294     strSQL=FormatSQL("update files set iTimesPlayed=%i where idFile=%i",
295                   ++iTimesPlayed, idFile);
296     m_pDS->exec(strSQL.c_str());
297     return true;
298   }
299   catch (...)
300   {
301     CLog::Log(LOGERROR, "CProgramDatabase:IncTimesPlayed(%s) failed", strFileName.c_str());
302   }
303
304   return false;
305 }
306
307 bool CProgramDatabase::SetDescription(const CStdString& strFileName, const CStdString& strDescription)
308 {
309   try
310   {
311     if (NULL == m_pDB.get()) return false;
312     if (NULL == m_pDS.get()) return false;
313
314     CStdString strSQL = FormatSQL("select * from files where files.strFileName like '%s'", strFileName.c_str());
315     if (!m_pDS->query(strSQL.c_str())) return false;
316     int iRowsFound = m_pDS->num_rows();
317     if (iRowsFound == 0)
318     {
319       m_pDS->close();
320       return false;
321     }
322     int idFile = m_pDS->fv("files.idFile").get_asLong();
323     m_pDS->close();
324
325     CLog::Log(LOGDEBUG, "CProgramDatabase::SetDescription(%s), idFile=%i, description=%s",
326               strFileName.c_str(), idFile,strDescription.c_str());
327
328     strSQL=FormatSQL("update files set xbedescription='%s' where idFile=%i",
329                   strDescription.c_str(), idFile);
330     m_pDS->exec(strSQL.c_str());
331     return true;
332   }
333   catch (...)
334   {
335     CLog::Log(LOGERROR, "CProgramDatabase:SetDescription(%s) failed", strFileName.c_str());
336   }
337
338   return false;
339 }