Merge pull request #2611 from MartijnKaijser/lang_ids
[vuplus_xbmc] / xbmc / BackgroundInfoLoader.cpp
1 /*
2  *      Copyright (C) 2005-2013 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, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "BackgroundInfoLoader.h"
22 #include "FileItem.h"
23 #include "settings/AdvancedSettings.h"
24 #include "threads/SingleLock.h"
25 #include "utils/log.h"
26
27 using namespace std;
28
29 #define ITEMS_PER_THREAD 5
30
31 CBackgroundInfoLoader::CBackgroundInfoLoader(int nThreads)
32 {
33   m_bStop = true;
34   m_pObserver=NULL;
35   m_pProgressCallback=NULL;
36   m_pVecItems = NULL;
37   m_nRequestedThreads = nThreads;
38   m_bStartCalled = false;
39   m_nActiveThreads = 0;
40 }
41
42 CBackgroundInfoLoader::~CBackgroundInfoLoader()
43 {
44   StopThread();
45 }
46
47 void CBackgroundInfoLoader::SetNumOfWorkers(int nThreads)
48 {
49   m_nRequestedThreads = nThreads;
50 }
51
52 void CBackgroundInfoLoader::Run()
53 {
54   try
55   {
56     if (m_vecItems.size() > 0)
57     {
58       {
59         CSingleLock lock(m_lock);
60         if (!m_bStartCalled)
61         {
62           OnLoaderStart();
63           m_bStartCalled = true;
64         }
65       }
66
67       while (!m_bStop)
68       {
69         CSingleLock lock(m_lock);
70         CFileItemPtr pItem;
71         vector<CFileItemPtr>::iterator iter = m_vecItems.begin();
72         if (iter != m_vecItems.end())
73         {
74           pItem = *iter;
75           m_vecItems.erase(iter);
76         }
77
78         if (pItem == NULL)
79           break;
80
81         // Ask the callback if we should abort
82         if ((m_pProgressCallback && m_pProgressCallback->Abort()) || m_bStop)
83           break;
84
85         lock.Leave();
86         try
87         {
88           if (LoadItem(pItem.get()) && m_pObserver)
89             m_pObserver->OnItemLoaded(pItem.get());
90         }
91         catch (...)
92         {
93           CLog::Log(LOGERROR, "%s::LoadItem - Unhandled exception for item %s", __FUNCTION__, pItem->GetPath().c_str());
94         }
95       }
96     }
97
98     CSingleLock lock(m_lock);
99     if (m_nActiveThreads == 1)
100       OnLoaderFinish();
101     m_nActiveThreads--;
102
103   }
104   catch (...)
105   {
106     m_nActiveThreads--;
107     CLog::Log(LOGERROR, "%s - Unhandled exception", __FUNCTION__);
108   }
109 }
110
111 void CBackgroundInfoLoader::Load(CFileItemList& items)
112 {
113   StopThread();
114
115   if (items.Size() == 0)
116     return;
117
118   CSingleLock lock(m_lock);
119
120   for (int nItem=0; nItem < items.Size(); nItem++)
121     m_vecItems.push_back(items[nItem]);
122
123   m_pVecItems = &items;
124   m_bStop = false;
125   m_bStartCalled = false;
126
127   int nThreads = m_nRequestedThreads;
128   if (nThreads == -1)
129     nThreads = (m_vecItems.size() / (ITEMS_PER_THREAD+1)) + 1;
130
131   if (nThreads > g_advancedSettings.m_bgInfoLoaderMaxThreads)
132     nThreads = g_advancedSettings.m_bgInfoLoaderMaxThreads;
133
134   m_nActiveThreads = nThreads;
135   for (int i=0; i < nThreads; i++)
136   {
137     CThread *pThread = new CThread(this, "BackgroundLoader");
138     pThread->Create();
139 #ifndef _LINUX
140     pThread->SetPriority(THREAD_PRIORITY_BELOW_NORMAL);
141 #endif
142     m_workers.push_back(pThread);
143   }
144
145 }
146
147 void CBackgroundInfoLoader::StopAsync()
148 {
149   m_bStop = true;
150 }
151
152
153 void CBackgroundInfoLoader::StopThread()
154 {
155   StopAsync();
156
157   for (int i=0; i<(int)m_workers.size(); i++)
158   {
159     m_workers[i]->StopThread();
160     delete m_workers[i];
161   }
162
163   m_workers.clear();
164   m_vecItems.clear();
165   m_pVecItems = NULL;
166   m_nActiveThreads = 0;
167 }
168
169 bool CBackgroundInfoLoader::IsLoading()
170 {
171   return m_nActiveThreads > 0;
172 }
173
174 void CBackgroundInfoLoader::SetObserver(IBackgroundLoaderObserver* pObserver)
175 {
176   m_pObserver = pObserver;
177 }
178
179 void CBackgroundInfoLoader::SetProgressCallback(IProgressCallback* pCallback)
180 {
181   m_pProgressCallback = pCallback;
182 }
183