00001
00002
00003
00004
00005
00006
00007 #include <QCoreApplication>
00008 #include <QRunnable>
00009
00010 #include "programinfocache.h"
00011 #include "mthreadpool.h"
00012 #include "mythlogging.h"
00013 #include "programinfo.h"
00014 #include "remoteutil.h"
00015 #include "mythevent.h"
00016
00017 typedef vector<ProgramInfo*> *VPI_ptr;
00018 static void free_vec(VPI_ptr &v)
00019 {
00020 if (v)
00021 {
00022 vector<ProgramInfo*>::iterator it = v->begin();
00023 for (; it != v->end(); ++it)
00024 delete *it;
00025 delete v;
00026 v = NULL;
00027 }
00028 }
00029
00030 class ProgramInfoLoader : public QRunnable
00031 {
00032 public:
00033 ProgramInfoLoader(ProgramInfoCache &c, const bool updateUI)
00034 : m_cache(c), m_updateUI(updateUI) {}
00035
00036 void run(void)
00037 {
00038 m_cache.Load(m_updateUI);
00039 }
00040
00041 ProgramInfoCache &m_cache;
00042 bool m_updateUI;
00043 };
00044
00045 ProgramInfoCache::ProgramInfoCache(QObject *o) :
00046 m_next_cache(NULL), m_listener(o),
00047 m_load_is_queued(false), m_loads_in_progress(0)
00048 {
00049 }
00050
00051 ProgramInfoCache::~ProgramInfoCache()
00052 {
00053 QMutexLocker locker(&m_lock);
00054
00055 while (m_loads_in_progress)
00056 m_load_wait.wait(&m_lock);
00057
00058 Clear();
00059 free_vec(m_next_cache);
00060 }
00061
00062 void ProgramInfoCache::ScheduleLoad(const bool updateUI)
00063 {
00064 QMutexLocker locker(&m_lock);
00065 if (!m_load_is_queued)
00066 {
00067 m_load_is_queued = true;
00068 m_loads_in_progress++;
00069 MThreadPool::globalInstance()->start(
00070 new ProgramInfoLoader(*this, updateUI), "ProgramInfoLoader");
00071 }
00072 }
00073
00074 void ProgramInfoCache::Load(const bool updateUI)
00075 {
00076 QMutexLocker locker(&m_lock);
00077 m_load_is_queued = false;
00078
00079 locker.unlock();
00080
00081
00082
00083 vector<ProgramInfo*> *tmp = RemoteGetRecordedList(0);
00084
00085 locker.relock();
00086
00087 free_vec(m_next_cache);
00088 m_next_cache = tmp;
00089
00090 if (updateUI)
00091 QCoreApplication::postEvent(
00092 m_listener, new MythEvent("UPDATE_UI_LIST"));
00093
00094 m_loads_in_progress--;
00095 m_load_wait.wakeAll();
00096 }
00097
00098 bool ProgramInfoCache::IsLoadInProgress(void) const
00099 {
00100 QMutexLocker locker(&m_lock);
00101 return m_loads_in_progress;
00102 }
00103
00104 void ProgramInfoCache::WaitForLoadToComplete(void) const
00105 {
00106 QMutexLocker locker(&m_lock);
00107 while (m_loads_in_progress)
00108 m_load_wait.wait(&m_lock);
00109 }
00110
00121 void ProgramInfoCache::Refresh(void)
00122 {
00123 QMutexLocker locker(&m_lock);
00124 if (m_next_cache)
00125 {
00126 Clear();
00127 vector<ProgramInfo*>::iterator it = m_next_cache->begin();
00128 for (; it != m_next_cache->end(); ++it)
00129 {
00130 if (!(*it)->GetChanID())
00131 continue;
00132
00133 PICKey k((*it)->GetChanID(), (*it)->GetRecordingStartTime());
00134 m_cache[k] = *it;
00135 }
00136 delete m_next_cache;
00137 m_next_cache = NULL;
00138 return;
00139 }
00140 locker.unlock();
00141
00142 Cache::iterator it = m_cache.begin();
00143 Cache::iterator nit = it;
00144 for (; it != m_cache.end(); it = nit)
00145 {
00146 nit = it;
00147 ++nit;
00148
00149 if (it->second->GetAvailableStatus() == asDeleted)
00150 {
00151 delete it->second;
00152 m_cache.erase(it);
00153 }
00154 }
00155 }
00156
00161 bool ProgramInfoCache::Update(const ProgramInfo &pginfo)
00162 {
00163 QMutexLocker locker(&m_lock);
00164
00165 Cache::iterator it = m_cache.find(
00166 PICKey(pginfo.GetChanID(),pginfo.GetRecordingStartTime()));
00167
00168 if (it != m_cache.end())
00169 it->second->clone(pginfo, true);
00170
00171 return it != m_cache.end();
00172 }
00173
00178 bool ProgramInfoCache::UpdateFileSize(
00179 uint chanid, const QDateTime &recstartts, uint64_t filesize)
00180 {
00181 QMutexLocker locker(&m_lock);
00182
00183 Cache::iterator it = m_cache.find(PICKey(chanid,recstartts));
00184
00185 if (it != m_cache.end())
00186 {
00187 it->second->SetFilesize(filesize);
00188 if (filesize)
00189 it->second->SetAvailableStatus(asAvailable, "PIC::UpdateFileSize");
00190 }
00191
00192 return it != m_cache.end();
00193 }
00194
00198 QString ProgramInfoCache::GetRecGroup(
00199 uint chanid, const QDateTime &recstartts) const
00200 {
00201 QMutexLocker locker(&m_lock);
00202
00203 Cache::const_iterator it = m_cache.find(PICKey(chanid,recstartts));
00204
00205 QString recgroup;
00206 if (it != m_cache.end())
00207 recgroup = it->second->GetRecordingGroup();
00208
00209 return recgroup;
00210 }
00211
00215 void ProgramInfoCache::Add(const ProgramInfo &pginfo)
00216 {
00217 if (!pginfo.GetChanID() || Update(pginfo))
00218 return;
00219
00220 PICKey key(pginfo.GetChanID(),pginfo.GetRecordingStartTime());
00221 m_cache[key] = new ProgramInfo(pginfo);
00222 }
00223
00229 bool ProgramInfoCache::Remove(uint chanid, const QDateTime &recstartts)
00230 {
00231 Cache::iterator it = m_cache.find(PICKey(chanid,recstartts));
00232
00233 if (it != m_cache.end())
00234 it->second->SetAvailableStatus(asDeleted, "PIC::Remove");
00235
00236 return it != m_cache.end();
00237 }
00238
00239 void ProgramInfoCache::GetOrdered(vector<ProgramInfo*> &list, bool newest_first)
00240 {
00241 if (newest_first)
00242 {
00243 Cache::reverse_iterator it = m_cache.rbegin();
00244 for (; it != m_cache.rend(); ++it)
00245 list.push_back(it->second);
00246 }
00247 else
00248 {
00249 for (Cache::iterator it = m_cache.begin(); it != m_cache.end(); ++it)
00250 list.push_back(it->second);
00251 }
00252 }
00253
00254 ProgramInfo *ProgramInfoCache::GetProgramInfo(
00255 uint chanid, const QDateTime &recstartts) const
00256 {
00257 Cache::const_iterator it = m_cache.find(PICKey(chanid,recstartts));
00258
00259 if (it != m_cache.end())
00260 return it->second;
00261
00262 return NULL;
00263 }
00264
00265 ProgramInfo *ProgramInfoCache::GetProgramInfo(const QString &piKey) const
00266 {
00267 uint chanid;
00268 QDateTime recstartts;
00269 if (ProgramInfo::ExtractKey(piKey, chanid, recstartts))
00270 return GetProgramInfo(chanid, recstartts);
00271 return NULL;
00272 }
00273
00275 void ProgramInfoCache::Clear(void)
00276 {
00277 for (Cache::iterator it = m_cache.begin(); it != m_cache.end(); ++it)
00278 delete it->second;
00279 m_cache.clear();
00280 }
00281