Initialize Tizen 2.3
[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         AppLogDebug("__pMutexCmd: %x", __pMutexCmd);
197
198         ThumbnailJob* pThumbnailJob = new (std::nothrow) ThumbnailJob();
199         AppLogDebug("pThumbnailJob: %x", pThumbnailJob);
200         pThumbnailJob->Construct(contentId, ++__requestId, event);
201         __pCmdQueue->Add(pThumbnailJob);
202
203         __pMutexCmd->Release();
204
205         SendUserEvent(null, null);
206         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
207 }
208
209 void
210 ThumbnailProvider::ClearThumbnailRequests(const bool appTerminating)
211 {
212         AppLogDebug("ENTER");
213         if (__pMutexCmd != null)
214         {
215                 __pMutexCmd->Acquire();
216                 if (__pCmdQueue != null && __pCmdQueue->GetCount() > 0)
217                 {
218                         __pCmdQueue->RemoveAll(true);
219                 }
220
221                 if (appTerminating == true)
222                 {
223                         __isAppTerminating = true;
224                 }
225                 __pMutexCmd->Release();
226         }
227         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
228 }
229
230 bool
231 ThumbnailProvider::OnStart(void)
232 {
233         AppLogDebug("ENTER");
234         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
235
236         return true;
237 }
238
239 void
240 ThumbnailProvider::OnStop(void)
241 {
242         AppLogDebug("ENTER");
243         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
244 }
245
246 void
247 ThumbnailProvider::OnUserEventReceivedN(RequestId requestId, IList* pArgs)
248 {
249         AppLogDebug("ENTER");
250         AppLogDebug("[THREAD] Receive Job Message - (SubThread)");
251         ThumbnailJob* pThumbnailJob = null;
252         ThumbnailInfo* pThumbnailInfo = null;
253         ContentId contentId;
254
255         if (__pMutexCmd == null || __pCmdQueue == null)
256         {
257                 delete pArgs;
258                 AppLogDebug("EXIT1(%s)", GetErrorMessage(GetLastResult()));
259                 return;
260         }
261
262         __pMutexCmd->Acquire();
263         if (__pCmdQueue->GetCount() > 0)
264         {
265                 pThumbnailJob = static_cast<ThumbnailJob*>(__pCmdQueue->GetAt(0));
266                 if (pThumbnailJob == null)
267                 {
268                         __pCmdQueue->RemoveAt(0);
269                         __pMutexCmd->Release();
270                         return;
271                 }
272
273                 unsigned long requestId = pThumbnailJob->GetRequestId();
274                 ContentId contentId = pThumbnailJob->GetContentId();
275                 __pMutexCmd->Release();
276
277                 pThumbnailInfo = GetThumbnailInfoN(contentId);
278
279                 __pMutexCmd->Acquire();
280                 pThumbnailJob = static_cast<ThumbnailJob*>(__pCmdQueue->GetAt(0));
281
282                 if (pThumbnailJob != null && pThumbnailInfo != null && requestId == pThumbnailJob->GetRequestId())
283                 {
284                         ContentType contentType = pThumbnailInfo->GetContentType();
285                         if (contentType == CONTENT_TYPE_IMAGE || contentType == CONTENT_TYPE_VIDEO)
286                         {
287                                 ThumbnailEvent* pThumbnailEvent = const_cast<ThumbnailEvent*>(pThumbnailJob->GetEvent());
288                                 if (pThumbnailEvent != null)
289                                 {
290                                         if (__isAppTerminating != true)
291                                         {
292                                                 ThumbnailEventArg* pSendingArg = new (std::nothrow)ThumbnailEventArg(pThumbnailInfo);
293                                                 pThumbnailEvent->Fire(*pSendingArg);
294                                         }
295                                 }
296                         }
297                         else
298                         {
299                                 delete pThumbnailInfo;
300                         }
301                         __pCmdQueue->RemoveAt(0, true);
302                 }
303                 else
304                 {
305                         delete pThumbnailInfo;
306                 }
307         }
308         __pMutexCmd->Release();
309
310         delete pArgs;
311
312         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
313 }
314
315 ThumbnailInfo*
316 ThumbnailProvider::GetThumbnailInfoN(const ContentId& contentId) const
317 {
318         AppLogDebug("ENTER");
319         ThumbnailInfo* pNewThumbnailInfo = null;
320
321         ContentManager contentManager;
322         result r = contentManager.Construct();
323         if (r == E_SUCCESS)
324         {
325                 Bitmap* pBitmap = null;
326                 long duration = 0;
327
328                 ContentInfo* pContentInfo = contentManager.GetContentInfoN(contentId);
329
330                 if (pContentInfo != null)
331                 {
332                         String path = pContentInfo->GetContentPath();
333                         if (path.EndsWith(L"tif") != true
334                                 && path.EndsWith(L"tiff") != true
335                                 && path.EndsWith(L"wbmp") != true
336                                 && path.EndsWith(L"TIF") != true
337                                 && path.EndsWith(L"TIFF") != true
338                                 && path.EndsWith(L"WBMP") != true)
339                         {
340                                 pBitmap = pContentInfo->GetThumbnailN();
341                         }
342
343                         if (pBitmap == null)
344                         {
345                                 pBitmap = GetThumbnailByDecodeN(pContentInfo->GetContentPath(), pContentInfo->GetContentType());
346                                 if (pBitmap == null)
347                                 {
348                                         pBitmap = ResourceManager::GetBitmapN(IDB_NO_CONTENTS_BROKEN);
349                                 }
350                         }
351                         pBitmap->Scale(DIMENSION_DEFAULT_THUMBNAIL);
352
353                         ContentType contentType = pContentInfo->GetContentType();
354
355                         if (contentType == CONTENT_TYPE_VIDEO)
356                         {
357                                 VideoContentInfo* pVideoContentInfo = static_cast<VideoContentInfo*>(pContentInfo);
358                                 duration = pVideoContentInfo->GetDuration();
359                         }
360
361                         pNewThumbnailInfo = new (std::nothrow) ThumbnailInfo();
362                         pNewThumbnailInfo->Construct(contentId, pContentInfo->GetContentPath(), *pBitmap, contentType, duration);
363                         delete pBitmap;
364                         delete pContentInfo;
365                 }
366         }
367         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
368
369         return pNewThumbnailInfo;
370 }
371
372 Bitmap*
373 ThumbnailProvider::GetThumbnailByDecodeN(const String& filePath, const ContentType contentType) const
374 {
375         AppLogDebug("ENTER");
376         Bitmap* pBitmap = null;
377         if (&filePath == null || filePath.GetLength() <= 0)
378         {
379                 pBitmap = new (std::nothrow) Bitmap();
380                 pBitmap->Construct(DIMENSION_DEFAULT_THUMBNAIL, BITMAP_PIXEL_FORMAT_RGB565);
381         }
382         else
383         {
384                 if (contentType == CONTENT_TYPE_IMAGE)
385                 {
386                         ImageBuffer pImageBuffer;
387                         result r = pImageBuffer.Construct(filePath);
388                         if (r == E_SUCCESS)
389                         {
390                                 pBitmap = pImageBuffer.GetBitmapN(BITMAP_PIXEL_FORMAT_ARGB8888, BUFFER_SCALING_AUTO);
391                         }
392                 }
393                 else if (contentType == CONTENT_TYPE_VIDEO)
394                 {
395                         VideoFrameExtractor extractor;
396                         result r = extractor.Construct(filePath, MEDIA_PIXEL_FORMAT_RGB565LE);
397                         if (r == E_SUCCESS)
398                         {
399                                 ImageBuffer* pImageBuffer = extractor.GetFrameN(0);
400                                 if (pImageBuffer != null)
401                                 {
402                                         pBitmap = pImageBuffer->GetBitmapN(BITMAP_PIXEL_FORMAT_RGB565, BUFFER_SCALING_AUTO);
403                                         delete pImageBuffer;
404                                 }
405                         }
406                 }
407         }
408         AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
409
410         return pBitmap;
411 }
412
413 String
414 ThumbnailProvider::GetFileNameFromFullPath(const String& fullPath, bool withExt) const
415 {
416         AppLogDebug("ENTER");
417         if (fullPath.CompareTo(EMPTY_SPACE) == 0)
418         {
419                 AppLogDebug("EXIT 1(%s)", GetErrorMessage(GetLastResult()));
420
421                 return EMPTY_SPACE;
422         }
423
424         String delim(DIRECTORY_SEPARATOR);
425         StringTokenizer st(fullPath,delim);
426         String token;
427         while (st.HasMoreTokens())
428         {
429                 st.GetNextToken(token);
430         }
431
432         if (withExt == true)
433         {
434                 AppLogDebug("EXIT 2(%s)", GetErrorMessage(GetLastResult()));
435
436                 return token;
437         }
438         else
439         {
440                 String subDelim(FILE_EXT_SEPARATOR);
441                 StringTokenizer subSt(token, subDelim);
442                 String subToken;
443                 subSt.GetNextToken(subToken);
444                 AppLogDebug("EXIT(%s)", GetErrorMessage(GetLastResult()));
445
446                 return subToken;
447         }
448 }