|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (developer.feedback@nokia.com) |
|
6 ** |
|
7 ** This file is part of the HbCore module of the UI Extensions for Mobile. |
|
8 ** |
|
9 ** GNU Lesser General Public License Usage |
|
10 ** This file may be used under the terms of the GNU Lesser General Public |
|
11 ** License version 2.1 as published by the Free Software Foundation and |
|
12 ** appearing in the file LICENSE.LGPL included in the packaging of this file. |
|
13 ** Please review the following information to ensure the GNU Lesser General |
|
14 ** Public License version 2.1 requirements will be met: |
|
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
16 ** |
|
17 ** In addition, as a special exception, Nokia gives you certain additional |
|
18 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
20 ** |
|
21 ** If you have questions regarding the use of this file, please contact |
|
22 ** Nokia at developer.feedback@nokia.com. |
|
23 ** |
|
24 ****************************************************************************/ |
|
25 |
|
26 #include "hbsplash_p.h" |
|
27 #include <QDir> |
|
28 #include <QFile> |
|
29 #include <QTime> |
|
30 |
|
31 #ifdef Q_OS_SYMBIAN |
|
32 #include <e32std.h> |
|
33 #include <f32file.h> |
|
34 #include "hborientationstatus_p.h" |
|
35 #include "hbsplashdefs_p.h" |
|
36 #endif |
|
37 |
|
38 /*! |
|
39 \class HbSplash |
|
40 |
|
41 \brief Class with utility functions for accessing splash screens. |
|
42 |
|
43 \internal |
|
44 */ |
|
45 |
|
46 const qint64 image_bytes_limit = 1024 * 1024 * 4; |
|
47 |
|
48 static QString orientationId(HbSplash::Flags flags) |
|
49 { |
|
50 if (flags & HbSplash::FixedVertical) { |
|
51 return QString("prt"); |
|
52 } else if (flags & HbSplash::FixedHorizontal) { |
|
53 return QString("lsc"); |
|
54 } |
|
55 #ifdef Q_OS_SYMBIAN |
|
56 Qt::Orientation orientation; |
|
57 if (HbOrientationStatus::currentOrientation(orientation) && orientation == Qt::Horizontal) { |
|
58 return QString("lsc"); |
|
59 } |
|
60 #endif |
|
61 return QString("prt"); |
|
62 } |
|
63 |
|
64 struct Params |
|
65 { |
|
66 int *w; |
|
67 int *h; |
|
68 int *bpl; |
|
69 QImage::Format *fmt; |
|
70 HbSplash::Flags flags; |
|
71 QString appId; |
|
72 HbSplash::AllocFunc allocFunc; |
|
73 void *allocFuncParam; |
|
74 }; |
|
75 |
|
76 struct File { |
|
77 qint64 read(char *buf, qint64 size); |
|
78 QString mFullName; |
|
79 #ifdef Q_OS_SYMBIAN |
|
80 RFile mFile; |
|
81 #else |
|
82 QFile mFile; |
|
83 #endif |
|
84 }; |
|
85 |
|
86 qint64 File::read(char *buf, qint64 size) |
|
87 { |
|
88 #ifdef Q_OS_SYMBIAN |
|
89 TPtr8 ptr(reinterpret_cast<unsigned char *>(buf), size); |
|
90 return mFile.Read(ptr, size) == KErrNone ? size : 0; |
|
91 #else |
|
92 return mFile.read(buf, size); |
|
93 #endif |
|
94 } |
|
95 |
|
96 static uchar *readSpl(File &f, const Params ¶ms) |
|
97 { |
|
98 int w = 0, h = 0, bpl = 0; |
|
99 QImage::Format fmt = QImage::Format_Invalid; |
|
100 f.read((char *) &w, sizeof(int)); |
|
101 f.read((char *) &h, sizeof(int)); |
|
102 f.read((char *) &bpl, sizeof(int)); |
|
103 f.read((char *) &fmt, sizeof(QImage::Format)); |
|
104 if (fmt != QImage::Format_ARGB32_Premultiplied) { |
|
105 qWarning("HbSplash: image format for %s is not ARGB32_PRE (is %d instead)", |
|
106 qPrintable(f.mFullName), fmt); |
|
107 } |
|
108 qint64 sz = h * bpl; |
|
109 uchar *data = 0; |
|
110 if (w > 0 && h > 0 && bpl > 0 && sz > 0 && sz <= image_bytes_limit) { |
|
111 try { |
|
112 if (params.allocFunc) { |
|
113 data = params.allocFunc(w, h, bpl, fmt, params.allocFuncParam); |
|
114 } else { |
|
115 data = new uchar[sz]; |
|
116 } |
|
117 if (data) { |
|
118 qint64 bytesRead = f.read((char *) data, sz); |
|
119 if (bytesRead != sz) { |
|
120 qWarning("HbSplash: file %s is invalid", qPrintable(f.mFullName)); |
|
121 if (!params.allocFunc) { |
|
122 delete data; |
|
123 } |
|
124 data = 0; |
|
125 } |
|
126 } |
|
127 } catch (const std::bad_alloc &) { |
|
128 qWarning("HbSplash: failed to allocate image buffer"); |
|
129 } |
|
130 } else { |
|
131 qWarning("HbSplash: image in file %s is too big", qPrintable(f.mFullName)); |
|
132 } |
|
133 *params.w = w; |
|
134 *params.h = h; |
|
135 *params.bpl = bpl; |
|
136 *params.fmt = fmt; |
|
137 return data; |
|
138 } |
|
139 |
|
140 #ifdef Q_OS_SYMBIAN |
|
141 |
|
142 class HbSplashSrvClient : public RSessionBase |
|
143 { |
|
144 public: |
|
145 bool Connect(); |
|
146 bool getSplash(RFile &f, const QString &ori, const QString &appId); |
|
147 }; |
|
148 |
|
149 bool HbSplashSrvClient::Connect() |
|
150 { |
|
151 TVersion ver(hbsplash_version_major, hbsplash_version_minor, hbsplash_version_build); |
|
152 if (CreateSession(hbsplash_server_name, ver) != KErrNone) { |
|
153 qWarning("[hbsplash] cannot connect to splashgen server"); |
|
154 return false; |
|
155 } |
|
156 return true; |
|
157 } |
|
158 |
|
159 bool HbSplashSrvClient::getSplash(RFile &f, const QString &ori, const QString &appId) |
|
160 { |
|
161 TPtrC oriDes(static_cast<const TUint16 *>(ori.utf16()), ori.length()); |
|
162 TPtrC appIdDes(static_cast<const TUint16 *>(appId.utf16()), appId.length()); |
|
163 TInt fileHandle; |
|
164 TPckg<TInt> fileHandlePckg(fileHandle); |
|
165 TIpcArgs args(&oriDes, &appIdDes, &fileHandlePckg); |
|
166 TInt fsHandle = SendReceive(HbSplashSrvGetSplash, args); |
|
167 return f.AdoptFromServer(fsHandle, fileHandle) == KErrNone; |
|
168 } |
|
169 |
|
170 static uchar *load_symbian(const Params ¶ms) |
|
171 { |
|
172 HbSplashSrvClient client; |
|
173 if (!client.Connect()) { |
|
174 return false; |
|
175 } |
|
176 |
|
177 QString oriStr(orientationId(params.flags)); |
|
178 QString appIdStr(params.appId); |
|
179 if (appIdStr.isEmpty()) { |
|
180 RProcess process; |
|
181 appIdStr = QString::number(process.SecureId().iId, 16); |
|
182 } |
|
183 |
|
184 uchar *data = 0; |
|
185 File f; |
|
186 f.mFullName = "[unavailable]"; |
|
187 if (client.getSplash(f.mFile, oriStr, appIdStr)) { |
|
188 qDebug("[hbsplash] got handle from server"); |
|
189 data = readSpl(f, params); |
|
190 f.mFile.Close(); |
|
191 } |
|
192 |
|
193 client.Close(); |
|
194 return data; |
|
195 } |
|
196 |
|
197 #else |
|
198 |
|
199 static uchar *read_file_generic(const QString &name, const Params ¶ms) |
|
200 { |
|
201 uchar *data = 0; |
|
202 File f; |
|
203 f.mFullName = name; |
|
204 f.mFile.setFileName(name); |
|
205 if (f.mFile.open(QIODevice::ReadOnly)) { |
|
206 data = readSpl(f, params); |
|
207 f.mFile.close(); |
|
208 } |
|
209 return data; |
|
210 } |
|
211 |
|
212 static uchar *load_generic(const Params ¶ms) |
|
213 { |
|
214 QString appSpecificName("splash_%1_%2.spl"); |
|
215 QString genericName("splash_%1.spl"); |
|
216 QDir dir("splashscreens"); // see hbsplashgenerator |
|
217 QString oriStr(orientationId(params.flags)); |
|
218 uchar *data = 0; |
|
219 // Try to read the app-specific screen. |
|
220 if (!params.appId.isEmpty()) { |
|
221 data = read_file_generic(dir.filePath(appSpecificName.arg(oriStr).arg(params.appId)), params); |
|
222 } |
|
223 // If failed then use the common one. |
|
224 if (!data) { |
|
225 data = read_file_generic(dir.filePath(genericName.arg(oriStr)), params); |
|
226 } |
|
227 return data; |
|
228 } |
|
229 |
|
230 #endif |
|
231 |
|
232 /*! |
|
233 Tries to find a suitable splash screen and returns the pixel data. The |
|
234 ownership of the returned pointer is transferred to the caller. |
|
235 |
|
236 When the return value is non-null then \a w, \a h, \a bpl, and \a fmt will be |
|
237 set to the width, height, bytes-per-line, format properties of the image data. |
|
238 |
|
239 If no suitable splash screens could be loaded then the return value is null. |
|
240 |
|
241 Symbian: By default the orientation depends on the current sensor status. |
|
242 |
|
243 Non-Symbian platforms: By default the screen for portrait orientation is used. |
|
244 |
|
245 \a flags can be used to override certain settings, e.g. to explicitly request |
|
246 the splash screen for a given orientation regardless of the platform or HW |
|
247 status. |
|
248 |
|
249 Symbian only: If \a appId is empty (the default value) then the secure id of the |
|
250 current process will be used to look up the application-specific screen. |
|
251 |
|
252 Non-Symbian platforms: If \a appId is empty then no application-specific screens |
|
253 will be searched. |
|
254 |
|
255 All platforms: If \a appId is not empty then it will be used as the application |
|
256 id when looking up application-specific screens. |
|
257 |
|
258 If the \a allocFunc function pointer is given then it will be called whenever |
|
259 a buffer is needed to be allocated. The function receives the following |
|
260 parameters: width, height, bytes-per-line, format, and the custom parameter \a |
|
261 allocFuncParam. This means that when allocFunc is not 0 the return value of |
|
262 load() is either 0 (if there was an error) or the return value of allocFunc |
|
263 (in case of success). |
|
264 |
|
265 \sa HbSplash::Flags |
|
266 |
|
267 \internal |
|
268 */ |
|
269 uchar *HbSplash::load(int &w, int &h, int &bpl, QImage::Format &fmt, |
|
270 Flags flags, const QString &appId, |
|
271 AllocFunc allocFunc, void *allocFuncParam) |
|
272 { |
|
273 Params params; |
|
274 params.w = &w; |
|
275 params.h = &h; |
|
276 params.bpl = &bpl; |
|
277 params.fmt = &fmt; |
|
278 params.flags = flags; |
|
279 params.appId = appId; |
|
280 params.allocFunc = allocFunc; |
|
281 params.allocFuncParam = allocFuncParam; |
|
282 #ifdef Q_OS_SYMBIAN |
|
283 return load_symbian(params); |
|
284 #else |
|
285 return load_generic(params); |
|
286 #endif |
|
287 } |