377ef46698b28a42ed8a1bbfabf4f7df8ad3a55b
[apps/osp/Gallery.git] / src / GlThumbnailProvider.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                GlThumbnailProvider.cpp
19  * @brief               This is the implementation file for ThumbnailProvider class.
20  */
21
22 #include <cstdlib>
23 #include <FContent.h>
24 #include <FMedia.h>
25 #include "GlResourceManager.h"
26 #include "GlThumbnailEvent.h"
27 #include "GlThumbnailEventArg.h"
28 #include "GlThumbnailJob.h"
29 #include "GlThumbnailProvider.h"
30 #include "GlTypes.h"
31
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 ThumbnailProvider* ThumbnailProvider::__pThumbnailProviderInstance = null;
41 ArrayList* ThumbnailProvider::__pThumbnailEventListener = null;
42
43 ThumbnailProvider::ThumbnailProvider(void)
44         : __pMutexCmd(null)
45         , __pCmdQueue(null)
46         , __requestId(0)
47         , __isAppTerminating(false)
48 {
49         AppLogDebug("ENTER");
50         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
51 }
52
53 ThumbnailProvider::~ThumbnailProvider(void)
54 {
55         AppLogDebug("ENTER");
56         if (__pThumbnailProviderInstance != null)
57         {
58                 __pThumbnailProviderInstance->Stop();
59                 __pThumbnailProviderInstance->Join();
60         }
61
62         if (__pThumbnailEventListener != null)
63         {
64                 delete __pThumbnailEventListener;
65         }
66
67         if (__pMutexCmd != null)
68         {
69                 delete __pMutexCmd;
70         }
71
72         if (__pCmdQueue != null)
73         {
74                 delete __pCmdQueue;
75         }
76         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
77 }
78
79 ThumbnailProvider*
80 ThumbnailProvider::GetInstance(void)
81 {
82         AppLogDebug("ENTER");
83         if (__pThumbnailProviderInstance == null)
84         {
85                 CreateInstance();
86                 __pThumbnailProviderInstance->Start();
87         }
88         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
89
90         return __pThumbnailProviderInstance;
91 }
92
93 result
94 ThumbnailProvider::Construct(void)
95 {
96         AppLogDebug("ENTER");
97
98         __pThumbnailEventListener = new (std::nothrow) ArrayList(SingleObjectDeleter);
99         result r = __pThumbnailEventListener->Construct();
100         TryCatch(r == E_SUCCESS, , "[%s] Unable to set event listener", GetErrorMessage(r));
101
102         __pMutexCmd = new (std::nothrow) Mutex();
103         r = __pMutexCmd->Create();
104         TryCatch(r == E_SUCCESS, , "[%s] Unable to create mutex", GetErrorMessage(r));
105
106         if (__pCmdQueue != null)
107         {
108                 delete __pCmdQueue;
109         }
110         __pCmdQueue = new (std::nothrow) ArrayList(SingleObjectDeleter);
111         r = __pCmdQueue->Construct();
112         TryCatch(r == E_SUCCESS, , "[%s] Unable to construct queue", GetErrorMessage(r));
113         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
114
115         return EventDrivenThread::Construct();
116
117 CATCH:
118         if (__pThumbnailEventListener != null)
119         {
120                 delete __pThumbnailEventListener;
121                 __pThumbnailEventListener = null;
122         }
123
124         if (__pMutexCmd != null)
125         {
126                 delete __pMutexCmd;
127                 __pMutexCmd = null;
128         }
129
130         if (__pCmdQueue != null)
131         {
132                 delete __pCmdQueue;
133                 __pCmdQueue = null;
134         }
135         AppLogDebug("EXIT with exception(%s)", GetErrorMessage(GetLastResult()));
136
137         return E_FAILURE;
138 }
139
140 void
141 ThumbnailProvider::CreateInstance(void)
142 {
143         AppLogDebug("ENTER");
144         __pThumbnailProviderInstance = new (std::nothrow) ThumbnailProvider();
145         result r = __pThumbnailProviderInstance->Construct();
146
147         if (IsFailed(r) == true)
148         {
149                 delete __pThumbnailProviderInstance;
150                 __pThumbnailProviderInstance = null;
151                 AppLogDebug("EXIT 1(%s)", GetErrorMessage(GetLastResult()));
152
153                 return;
154         }
155
156         std::atexit(DestroyInstance);
157         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
158 }
159
160 void
161 ThumbnailProvider::DestroyInstance(void)
162 {
163         AppLogDebug("ENTER");
164         delete __pThumbnailProviderInstance;
165         __pThumbnailProviderInstance = null;
166         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
167 }
168
169 void
170 ThumbnailProvider::Release(void)
171 {
172         AppLogDebug("ENTER");
173         if (__pThumbnailProviderInstance != null)
174         {
175                 delete __pThumbnailProviderInstance;
176                 __pThumbnailProviderInstance = null;
177         }
178         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
179 }
180
181 void
182 ThumbnailProvider::RequestThumbnail(const ContentId& contentId, const ThumbnailEvent* event)
183 {
184         AppLogDebug("ENTER");
185         AppLogDebug("[THREAD] Request Job - (MainThread)");
186
187         if (contentId.ToString().IsEmpty() == true || event == null
188                                 || __pMutexCmd == null || __pCmdQueue == null)
189         {
190                 AppLogDebug("EXIT 1(%s)", GetErrorMessage(GetLastResult()));
191                 return;
192         }
193
194         __pMutexCmd->Acquire();
195
196         ThumbnailJob* pThumbnailJob = new (std::nothrow) ThumbnailJob();
197         pThumbnailJob->Construct(contentId, ++__requestId, event);
198         __pCmdQueue->Add(pThumbnailJob);
199
200         __pMutexCmd->Release();
201
202         SendUserEvent(null, null);
203         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
204 }
205
206 void
207 ThumbnailProvider::ClearThumbnailRequests(const bool appTerminating)
208 {
209         AppLogDebug("ENTER");
210         if (__pMutexCmd != null)
211         {
212                 __pMutexCmd->Acquire();
213                 if (__pCmdQueue != null && __pCmdQueue->GetCount() > 0)
214                 {
215                         __pCmdQueue->RemoveAll(true);
216                 }
217
218                 if (appTerminating == true)
219                 {
220                         __isAppTerminating = true;
221                 }
222                 __pMutexCmd->Release();
223         }
224         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
225 }
226
227 bool
228 ThumbnailProvider::OnStart(void)
229 {
230         AppLogDebug("ENTER");
231         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
232
233         return true;
234 }
235
236 void
237 ThumbnailProvider::OnStop(void)
238 {
239         AppLogDebug("ENTER");
240         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
241 }
242
243 void
244 ThumbnailProvider::OnUserEventReceivedN(RequestId requestId, IList* pArgs)
245 {
246         AppLogDebug("ENTER");
247         AppLogDebug("[THREAD] Receive Job Message - (SubThread)");
248         ThumbnailJob* pThumbnailJob = null;
249         ThumbnailInfo* pThumbnailInfo = null;
250         ContentId contentId;
251
252         if (__pMutexCmd == null || __pCmdQueue == null)
253         {
254                 delete pArgs;
255                 AppLogDebug("EXIT1(%s)", GetErrorMessage(GetLastResult()));
256                 return;
257         }
258
259         __pMutexCmd->Acquire();
260         if (__pCmdQueue->GetCount() > 0)
261         {
262                 pThumbnailJob = static_cast<ThumbnailJob*>(__pCmdQueue->GetAt(0));
263                 if (pThumbnailJob == null)
264                 {
265                         __pCmdQueue->RemoveAt(0);
266                         __pMutexCmd->Release();
267                         return;
268                 }
269
270                 unsigned long requestId = pThumbnailJob->GetRequestId();
271                 ContentId contentId = pThumbnailJob->GetContentId();
272                 __pMutexCmd->Release();
273
274                 pThumbnailInfo = GetThumbnailInfoN(contentId);
275
276                 __pMutexCmd->Acquire();
277                 pThumbnailJob = static_cast<ThumbnailJob*>(__pCmdQueue->GetAt(0));
278
279                 if (pThumbnailJob != null && pThumbnailInfo != null && requestId == pThumbnailJob->GetRequestId())
280                 {
281                         ContentType contentType = pThumbnailInfo->GetContentType();
282                         if (contentType == CONTENT_TYPE_IMAGE || contentType == CONTENT_TYPE_VIDEO)
283                         {
284                                 ThumbnailEvent* pThumbnailEvent = const_cast<ThumbnailEvent*>(pThumbnailJob->GetEvent());
285                                 if (pThumbnailEvent != null)
286                                 {
287                                         if (__isAppTerminating != true)
288                                         {
289                                                 ThumbnailEventArg* pSendingArg = new (std::nothrow)ThumbnailEventArg(pThumbnailInfo);
290                                                 pThumbnailEvent->Fire(*pSendingArg);
291                                         }
292                                 }
293                         }
294                         else
295                         {
296                                 delete pThumbnailInfo;
297                         }
298                         __pCmdQueue->RemoveAt(0, true);
299                 }
300                 else
301                 {
302                         delete pThumbnailInfo;
303                 }
304         }
305         __pMutexCmd->Release();
306
307         delete pArgs;
308
309         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
310 }
311
312 ThumbnailInfo*
313 ThumbnailProvider::GetThumbnailInfoN(const ContentId& contentId) const
314 {
315         AppLogDebug("ENTER");
316         ThumbnailInfo* pNewThumbnailInfo = null;
317
318         ContentManager contentManager;
319         result r = contentManager.Construct();
320         if (r == E_SUCCESS)
321         {
322                 Bitmap* pBitmap = null;
323                 long duration = 0;
324
325                 ContentInfo* pContentInfo = contentManager.GetContentInfoN(contentId);
326
327                 if (pContentInfo != null)
328                 {
329                         String path = pContentInfo->GetContentPath();
330                         if (path.EndsWith(L"tif") != true
331                                 && path.EndsWith(L"tiff") != true
332                                 && path.EndsWith(L"wbmp") != true)
333                         {
334                                 pBitmap = pContentInfo->GetThumbnailN();
335                         }
336
337                         if (pBitmap == null)
338                         {
339                                 pBitmap = GetThumbnailByDecodeN(pContentInfo->GetContentPath(), pContentInfo->GetContentType());
340                                 if (pBitmap == null)
341                                 {
342                                         pBitmap = ResourceManager::GetBitmapN(IDB_NO_CONTENTS_BROKEN);
343                                 }
344                         }
345                         pBitmap->Scale(DIMENSION_DEFAULT_THUMBNAIL);
346
347                         ContentType contentType = pContentInfo->GetContentType();
348
349                         if (contentType == CONTENT_TYPE_VIDEO)
350                         {
351                                 VideoContentInfo* pVideoContentInfo = static_cast<VideoContentInfo*>(pContentInfo);
352                                 duration = pVideoContentInfo->GetDuration();
353                         }
354
355                         pNewThumbnailInfo = new (std::nothrow) ThumbnailInfo();
356                         pNewThumbnailInfo->Construct(contentId, pContentInfo->GetContentPath(), *pBitmap, contentType, duration);
357                         delete pBitmap;
358                 }
359         }
360         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
361
362         return pNewThumbnailInfo;
363 }
364
365 Bitmap*
366 ThumbnailProvider::GetThumbnailByDecodeN(const String& filePath, const ContentType contentType) const
367 {
368         AppLogDebug("ENTER");
369         Bitmap* pBitmap = null;
370         if (&filePath == null || filePath.GetLength() <= 0)
371         {
372                 pBitmap = new (std::nothrow) Bitmap();
373                 pBitmap->Construct(DIMENSION_DEFAULT_THUMBNAIL, BITMAP_PIXEL_FORMAT_RGB565);
374         }
375         else
376         {
377                 if (contentType == CONTENT_TYPE_IMAGE)
378                 {
379                         ImageBuffer pImageBuffer;
380                         result r = pImageBuffer.Construct(filePath);
381                         if (r == E_SUCCESS)
382                         {
383                                 pBitmap = pImageBuffer.GetBitmapN(BITMAP_PIXEL_FORMAT_ARGB8888, BUFFER_SCALING_AUTO);
384                         }
385                 }
386                 else if (contentType == CONTENT_TYPE_VIDEO)
387                 {
388                         VideoFrameExtractor extractor;
389                         result r = extractor.Construct(filePath, MEDIA_PIXEL_FORMAT_RGB565LE);
390                         if (r == E_SUCCESS)
391                         {
392                                 ImageBuffer* pImageBuffer = extractor.GetFrameN(0);
393                                 if (pImageBuffer != null)
394                                 {
395                                         pBitmap = pImageBuffer->GetBitmapN(BITMAP_PIXEL_FORMAT_RGB565, BUFFER_SCALING_AUTO);
396                                         delete pImageBuffer;
397                                 }
398                         }
399                 }
400         }
401         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
402
403         return pBitmap;
404 }
405
406 String
407 ThumbnailProvider::GetFileNameFromFullPath(const String& fullPath, bool withExt) const
408 {
409         AppLogDebug("ENTER");
410         if (fullPath.CompareTo(EMPTY_SPACE) == 0)
411         {
412                 AppLogDebug("EXIT 1(%s)", GetErrorMessage(GetLastResult()));
413
414                 return EMPTY_SPACE;
415         }
416
417         String delim(DIRECTORY_SEPARATOR);
418         StringTokenizer st(fullPath,delim);
419         String token;
420         while (st.HasMoreTokens())
421         {
422                 st.GetNextToken(token);
423         }
424
425         if (withExt == true)
426         {
427                 AppLogDebug("EXIT 2(%s)", GetErrorMessage(GetLastResult()));
428
429                 return token;
430         }
431         else
432         {
433                 String subDelim(FILE_EXT_SEPARATOR);
434                 StringTokenizer subSt(token, subDelim);
435                 String subToken;
436                 subSt.GetNextToken(subToken);
437                 AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
438
439                 return subToken;
440         }
441 }