Applied latest source code
[apps/native/preloaded/MusicPlayer.git] / src / MpThumbnailProvider.cpp
1 //
2 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
3 //
4 // Licensed under the Flora License, Version 1.1 (the License);
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://floralicense.org/license/
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an AS IS BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 /**
18  * @file                MpThumbnailProvider.cpp
19  * @brief               This is the implementation file for ThumbnailProvider class.
20  */
21
22 #include <cstdlib>
23 #include <FApp.h>
24 #include <FContent.h>
25 #include <FMedia.h>
26 #include "MpThumbnailEvent.h"
27 #include "MpThumbnailEventArg.h"
28 #include "MpThumbnailJob.h"
29 #include "MpThumbnailProvider.h"
30
31 using namespace Tizen::App;
32 using namespace Tizen::Base;
33 using namespace Tizen::Base::Collection;
34 using namespace Tizen::Base::Runtime;
35 using namespace Tizen::Base::Utility;
36 using namespace Tizen::Content;
37 using namespace Tizen::Graphics;
38 using namespace Tizen::Media;
39
40 static const int W_THUMBNAIL = 112;
41 static const int H_THUMBNAIL = 112;
42 static const Tizen::Base::String DEFAULT_THUMBNAIL = L"34_thumb_07.png";
43
44 ThumbnailProvider* ThumbnailProvider::__pThumbnailProviderInstance = null;
45
46 ThumbnailProvider::ThumbnailProvider(void)
47         : __pMutexCmd(null)
48         , __pCmdQueue(null)
49         , __pDefaultThumbnail(null)
50         , __requestId(0)
51         , __isForceClose(false)
52 {
53         AppLogDebug("ENTER");
54         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
55 }
56
57 ThumbnailProvider::~ThumbnailProvider(void)
58 {
59         AppLogDebug("ENTER");
60         if (__pThumbnailProviderInstance != null)
61         {
62                 __pThumbnailProviderInstance->Stop();
63                 __pThumbnailProviderInstance->Join();
64         }
65
66         if (__pMutexCmd != null)
67         {
68                 delete __pMutexCmd;
69         }
70
71         if (__pCmdQueue != null)
72         {
73                 delete __pCmdQueue;
74         }
75
76         DestroyDefaultThumbnailBitmap();
77         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
78 }
79
80 IThumbnailProviderHandler*
81 ThumbnailProvider::GetInstance(void)
82 {
83         AppLogDebug("ENTER");
84         if (__pThumbnailProviderInstance == null)
85         {
86                 if (!IsFailed(CreateInstance()))
87                 {
88                         __pThumbnailProviderInstance->Start();
89                 }
90         }
91
92         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
93         return __pThumbnailProviderInstance;
94 }
95
96 result
97 ThumbnailProvider::Construct(void)
98 {
99         AppLogDebug("ENTER");
100         __pMutexCmd = new (std::nothrow) Mutex();
101         result r = __pMutexCmd->Create();
102         TryCatch(r == E_SUCCESS, , "[%s] Unable to create mutex", GetErrorMessage(r));
103
104         if (__pCmdQueue != null)
105         {
106                 delete __pCmdQueue;
107                 __pCmdQueue = null;
108         }
109         __pCmdQueue = new (std::nothrow) ArrayList(SingleObjectDeleter);
110         r = __pCmdQueue->Construct();
111         TryCatch(r == E_SUCCESS, , "[%s] Unable to construct queue", GetErrorMessage(r));
112
113         CreateDefaultThumbnailBitmap();
114         __isForceClose = false;
115         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
116         return EventDrivenThread::Construct();
117
118 CATCH:
119         if (__pMutexCmd != null)
120         {
121                 delete __pMutexCmd;
122                 __pMutexCmd = null;
123         }
124
125         if (__pCmdQueue != null)
126         {
127                 delete __pCmdQueue;
128                 __pCmdQueue = null;
129         }
130
131         AppLogDebug("EXIT with exception(%s)", GetErrorMessage(GetLastResult()));
132         return E_FAILURE;
133 }
134
135 result
136 ThumbnailProvider::CreateInstance(void)
137 {
138         AppLogDebug("ENTER");
139         __pThumbnailProviderInstance = new (std::nothrow) ThumbnailProvider();
140         result r = __pThumbnailProviderInstance->Construct();
141         if (IsFailed(r))
142         {
143                 delete __pThumbnailProviderInstance;
144                 __pThumbnailProviderInstance = null;
145                 AppLogDebug("EXIT 1(%s)", GetErrorMessage(GetLastResult()));
146
147                 return r;
148         }
149
150         std::atexit(DestroyInstance);
151         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
152         return E_SUCCESS;
153 }
154
155 void
156 ThumbnailProvider::DestroyInstance(void)
157 {
158         AppLogDebug("ENTER");
159         delete __pThumbnailProviderInstance;
160         __pThumbnailProviderInstance = null;
161         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
162 }
163
164 void
165 ThumbnailProvider::Release(void)
166 {
167         AppLogDebug("ENTER");
168         if (__pThumbnailProviderInstance != null)
169         {
170                 delete __pThumbnailProviderInstance;
171                 __pThumbnailProviderInstance = null;
172         }
173         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
174 }
175
176 void
177 ThumbnailProvider::RequestThumbnail(const ContentId& contentId, const ThumbnailEvent* event, Tizen::Base::Object* pParam)
178 {
179         AppLogDebug("ENTER");
180         AppLogDebug("[THREAD] Request Job - (MainThread)");
181
182         if (contentId.ToString().IsEmpty() == true || event == null
183                 || __pMutexCmd == null || __pCmdQueue == null || __isForceClose == true)
184         {
185                 AppLogDebug("EXIT 1(%s)", GetErrorMessage(GetLastResult()));
186                 delete pParam;
187                 return;
188         }
189
190         __pMutexCmd->Acquire();
191
192         ThumbnailJob* pThumbnailJob = new (std::nothrow) ThumbnailJob();
193         pThumbnailJob->Construct(contentId, ++__requestId, event, pParam);
194         __pCmdQueue->Add(pThumbnailJob);
195
196         __pMutexCmd->Release();
197
198         SendUserEvent(null, null);
199         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
200 }
201
202 void
203 ThumbnailProvider::CancelThumbnailRequest(const ContentId& contentId, const ThumbnailEvent* event)
204 {
205         AppLogDebug("ENTER");
206         ThumbnailJob* pThumbnailJob = null;
207
208         __pMutexCmd->Acquire();
209
210         int loopCount = __pCmdQueue->GetCount();
211         for (int i = 0; i < loopCount; ++i)
212         {
213                 pThumbnailJob = static_cast<ThumbnailJob*>(__pCmdQueue->GetAt(i));
214
215                 if (pThumbnailJob != null
216                         && pThumbnailJob->GetContentId() == contentId
217                         && pThumbnailJob->GetEvent() == event)
218                 {
219                         AppLogDebug("ENTER i(%d) event(%x)", i, event);
220                         __pCmdQueue->RemoveAt(i, true);
221                         break;
222                 }
223         }
224         __pMutexCmd->Release();
225         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
226 }
227
228 void
229 ThumbnailProvider::CancelAllThumbnailRequest(const ThumbnailEvent* event)
230 {
231         AppLogDebug("ENTER");
232         ThumbnailJob* pThumbnailJob = null;
233
234         __pMutexCmd->Acquire();
235         int loopCount = __pCmdQueue->GetCount();
236         for (int i = 0; i < loopCount; ++i)
237         {
238                 pThumbnailJob = static_cast<ThumbnailJob*>(__pCmdQueue->GetAt(i));
239
240                 if (pThumbnailJob != null
241                         && pThumbnailJob->GetEvent() == event)
242                 {
243                         AppLogDebug("ENTER i(%d) event(%x)", i, event);
244                         __pCmdQueue->RemoveAt(i, true);
245                 }
246         }
247         __pMutexCmd->Release();
248         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
249 }
250
251 void
252 ThumbnailProvider::ClearThumbnailRequests(void)
253 {
254         AppLogDebug("ENTER");
255         if(__pCmdQueue != null)
256         {
257                 __pCmdQueue->RemoveAll(true);
258         }
259         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
260 }
261
262 const Tizen::Graphics::Bitmap*
263 ThumbnailProvider::GetDefaultThumbnail(void) const
264 {
265         AppLogDebug("ENTER");
266         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
267         return __pDefaultThumbnail;
268 }
269
270 bool
271 ThumbnailProvider::OnStart(void)
272 {
273         AppLogDebug("ENTER");
274         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
275         return true;
276 }
277
278 void
279 ThumbnailProvider::OnStop(void)
280 {
281         AppLogDebug("ENTER");
282         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
283 }
284
285 result
286 ThumbnailProvider::Quit(void)
287 {
288         AppLogDebug("ENTER");
289         __pMutexCmd->Acquire();
290         __isForceClose = true;
291         ClearThumbnailRequests();
292         __pMutexCmd->Release();
293         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
294         return EventDrivenThread::Quit();
295 }
296
297 void
298 ThumbnailProvider::OnUserEventReceivedN(RequestId requestId, IList* pArgs)
299 {
300         AppLogDebug("ENTER");
301         AppLogDebug("[THREAD] Receive Job Message - (SubThread)");
302         if (__pMutexCmd == null || __pCmdQueue == null)
303         {
304                 delete pArgs;
305                 AppLogDebug("EXIT1(%s)", GetErrorMessage(GetLastResult()));
306                 return;
307         }
308
309         __pMutexCmd->Acquire();
310         if (__pCmdQueue->GetCount() > 0)
311         {
312                 ThumbnailJob* pThumbnailJob = static_cast<ThumbnailJob*>(__pCmdQueue->GetAt(0));
313                 if (pThumbnailJob == null)
314                 {
315                         __pCmdQueue->RemoveAt(0);
316                         __pMutexCmd->Release();
317                         return;
318                 }
319
320                 unsigned long requestId = pThumbnailJob->GetRequestId();
321                 ContentId contentId = pThumbnailJob->GetContentId();
322 //              __pMutexCmd->Release();
323
324                 ThumbnailInfo* pThumbnailInfo = GetThumbnailInfoN(contentId, pThumbnailJob->GetUserParamN());
325                 if (pThumbnailInfo == null)
326                 {
327 //                      __pMutexCmd->Acquire();
328                         __pCmdQueue->RemoveAt(0, true);
329                         __pMutexCmd->Release();
330                         AppLogDebug("pThumbnailInfo null");
331                         return;
332                 }
333
334 //              __pMutexCmd->Acquire();
335                 pThumbnailJob = static_cast<ThumbnailJob*>(__pCmdQueue->GetAt(0));
336                 if (pThumbnailJob != null && requestId == pThumbnailJob->GetRequestId())
337                 {
338                         ThumbnailEvent* pThumbnailEvent = const_cast<ThumbnailEvent*>(pThumbnailJob->GetEvent());
339                         if (pThumbnailEvent != null && __isForceClose == false)
340                         {
341                                 ThumbnailEventArg* pSendingArg = new (std::nothrow) ThumbnailEventArg(pThumbnailInfo);
342                                 pThumbnailEvent->Fire(*pSendingArg);
343                                 pThumbnailInfo = null;
344                         }
345
346                         __pCmdQueue->RemoveAt(0, true);
347                         if (pThumbnailInfo != null)
348                         {
349                                 delete pThumbnailInfo;
350                                 pThumbnailInfo = null;
351                         }
352                 }
353                 else
354                 {
355                         __pCmdQueue->RemoveAt(0, true);
356                         delete pThumbnailInfo;
357                 }
358         }
359         __pMutexCmd->Release();
360
361         delete pArgs;
362         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
363 }
364
365 ThumbnailInfo*
366 ThumbnailProvider::GetThumbnailInfoN(const ContentId& contentId, Tizen::Base::Object* pParam) const
367 {
368         AppLogDebug("ENTER");
369         ThumbnailInfo* pNewThumbnailInfo = null;
370         Bitmap* pBitmap = null;
371         ContentInfo* pContentInfo = null;
372
373         ContentManager contentManager;
374         result r = contentManager.Construct();
375         TryCatch(r == E_SUCCESS, , "ContentManager.Construct() failed(%s)", GetErrorMessage(r));
376
377         pContentInfo = contentManager.GetContentInfoN(contentId);
378         TryCatch(GetLastResult() == E_SUCCESS, , "ContentManager.GetContentInfoN() failed(%s)", GetErrorMessage(r));
379         TryCatch(pContentInfo != null, delete pContentInfo, "pContentInfo is null(%s)", GetErrorMessage(GetLastResult()));
380
381         pBitmap = pContentInfo->GetThumbnailN();
382         if (pBitmap == null)
383         {
384                 pBitmap = GetThumbnailByDecodeN(pContentInfo->GetContentPath(), pContentInfo->GetContentType());
385                 TryCatch(pBitmap != null, delete pContentInfo; pContentInfo = null , "GetThumbnailByDecodeN failed(%s)", GetErrorMessage(GetLastResult()));
386         }
387         pBitmap->Scale(Dimension(W_THUMBNAIL, H_THUMBNAIL));
388
389         pNewThumbnailInfo = new (std::nothrow) ThumbnailInfo();
390         pNewThumbnailInfo->Construct(contentId, *pBitmap, pParam);
391
392         AppLogDebug("EXIT");
393         delete pContentInfo;
394         return pNewThumbnailInfo;
395
396 CATCH:
397         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
398         return null;
399 }
400
401 Bitmap*
402 ThumbnailProvider::GetThumbnailByDecodeN(const String& filePath, const ContentType contentType) const
403 {
404         AppLogDebug("ENTER");
405         Bitmap* pBitmap = null;
406         if (&filePath == null || filePath.GetLength() <= 0)
407         {
408                 pBitmap = new (std::nothrow) Bitmap();
409                 if (__pDefaultThumbnail != null)
410                 {
411                         pBitmap->Construct(*__pDefaultThumbnail,FloatRectangle(0,0,__pDefaultThumbnail->GetWidthF(),__pDefaultThumbnail->GetHeightF()));
412                         pBitmap->Scale(Dimension(W_THUMBNAIL, H_THUMBNAIL));
413                 }
414                 else
415                 {
416                         pBitmap->Construct(Dimension(W_THUMBNAIL, H_THUMBNAIL), BITMAP_PIXEL_FORMAT_RGB565);
417                 }
418         }
419         else
420         {
421                 AudioMetadata* pAudioMeta = ContentManagerUtil::GetAudioMetaN(filePath);
422                 TryReturn(pAudioMeta != null, null, "filepath is [%ls]", filePath.GetPointer());
423
424                 pBitmap = pAudioMeta->GetAlbumArtN();
425                 delete pAudioMeta;
426                 if (pBitmap == null)
427                 {
428                         if (__pDefaultThumbnail != null)
429                         {
430                                 pBitmap = new (std::nothrow) Bitmap();
431                                 pBitmap->Construct(*__pDefaultThumbnail,FloatRectangle(0,0,__pDefaultThumbnail->GetWidthF(),__pDefaultThumbnail->GetHeightF()));
432                                 pBitmap->Scale(Dimension(W_THUMBNAIL, H_THUMBNAIL));
433                         }
434                         AppLogDebug("There is not a AlbumArt image");
435                         return pBitmap;
436                 }
437
438                 pBitmap->Scale(Dimension(W_THUMBNAIL, H_THUMBNAIL));
439         }
440
441         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
442         return pBitmap;
443 }
444
445 void
446 ThumbnailProvider::CreateDefaultThumbnailBitmap(void)
447 {
448         AppLogDebug("ENTER");
449         AppResource* pAppResource = Application::GetInstance()->GetAppResource();
450         __pDefaultThumbnail = pAppResource->GetBitmapN(DEFAULT_THUMBNAIL);
451         __pDefaultThumbnail->Scale(Dimension(W_THUMBNAIL, H_THUMBNAIL));
452         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
453 }
454
455 void
456 ThumbnailProvider::DestroyDefaultThumbnailBitmap(void)
457 {
458         AppLogDebug("ENTER");
459         delete __pDefaultThumbnail;
460         __pDefaultThumbnail = null;
461         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
462 }