src/hbcore/gui/hbsplash.cpp
branchGCC_SURGE
changeset 15 f378acbc9cfb
parent 5 627c4a0fd0e7
child 21 4633027730f5
child 34 ed14f46c0e55
equal deleted inserted replaced
9:730c025d4b77 15:f378acbc9cfb
    22 ** Nokia at developer.feedback@nokia.com.
    22 ** Nokia at developer.feedback@nokia.com.
    23 **
    23 **
    24 ****************************************************************************/
    24 ****************************************************************************/
    25 
    25 
    26 #include "hbsplash_p.h"
    26 #include "hbsplash_p.h"
       
    27 #include "hbsplash_direct_symbian_p.h"
    27 #include <QDir>
    28 #include <QDir>
    28 #include <QFile>
    29 #include <QFile>
    29 #include <QTime>
    30 #include <QTime>
       
    31 #include <QScopedPointer>
    30 
    32 
    31 #ifdef Q_OS_SYMBIAN
    33 #ifdef Q_OS_SYMBIAN
    32 #include <e32std.h>
    34 #include <e32std.h>
    33 #include <f32file.h>
    35 #include <f32file.h>
       
    36 #include <fbs.h>
    34 #include "hborientationstatus_p.h"
    37 #include "hborientationstatus_p.h"
    35 #include "hbsplashdefs_p.h"
    38 #include "hbsplashdefs_p.h"
    36 #endif
    39 #endif
    37 
    40 
    38 /*!
    41 /*!
    39   \class HbSplash
    42   \class HbSplash
    40   
    43 
    41   \brief Class with utility functions for accessing splash screens.
    44   \brief Class with utility functions for accessing splash screens.
    42 
    45 
    43   \internal
    46   \internal
    44 */
    47 */
    45 
    48 
    59     }
    62     }
    60 #endif
    63 #endif
    61     return QString("prt");
    64     return QString("prt");
    62 }
    65 }
    63 
    66 
    64 struct Params
    67 struct Params {
    65 {
       
    66     int *w;
    68     int *w;
    67     int *h;
    69     int *h;
    68     int *bpl;
    70     int *bpl;
    69     QImage::Format *fmt;
    71     QImage::Format *fmt;
    70     HbSplashScreen::Flags flags;
    72     HbSplashScreen::Flags flags;
    71     QString appId;
    73     QString appId;
    72     QString screenId;
    74     QString screenId;
    73     HbSplash::AllocFunc allocFunc;
    75     HbSplash::AllocFunc allocFunc;
    74     void *allocFuncParam;
    76     void *allocFuncParam;
       
    77     quint32 extra;
       
    78     bool forceFile;
    75 };
    79 };
    76 
    80 
    77 struct File {
    81 struct File {
    78     qint64 read(char *buf, qint64 size);
    82     qint64 read(char *buf, qint64 size);
    79     QString mFullName;
    83     QString mFullName;
    92 #else
    96 #else
    93     return mFile.read(buf, size);
    97     return mFile.read(buf, size);
    94 #endif
    98 #endif
    95 }
    99 }
    96 
   100 
    97 static uchar *readSpl(File &f, const Params &params)
   101 static uchar *readSpl(File &f, Params &params)
    98 {
   102 {
    99     int w = 0, h = 0, bpl = 0;
   103     quint32 w = 0, h = 0, bpl = 0;
   100     QImage::Format fmt = QImage::Format_Invalid;
   104     QImage::Format fmt = QImage::Format_Invalid;
   101     f.read((char *) &w, sizeof(int));
   105     // Have to read the header in one piece in order to minimize the
   102     f.read((char *) &h, sizeof(int));
   106     // number of read() calls.
   103     f.read((char *) &bpl, sizeof(int));
   107     const int headerLength = sizeof(quint32) * 5;
   104     f.read((char *) &fmt, sizeof(QImage::Format));
   108     char headerBuf[headerLength];
       
   109     qMemSet(headerBuf, 0, headerLength);
       
   110     f.read(headerBuf, headerLength);
       
   111     quint32 *headerPtr = reinterpret_cast<quint32 *>(headerBuf);
       
   112     w = *headerPtr++;
       
   113     h = *headerPtr++;
       
   114     bpl = *headerPtr++;
       
   115     fmt = (QImage::Format) * headerPtr++;
       
   116     params.extra = *headerPtr;
   105     if (fmt != QImage::Format_ARGB32_Premultiplied) {
   117     if (fmt != QImage::Format_ARGB32_Premultiplied) {
   106         qWarning("HbSplash: image format for %s is not ARGB32_PRE (is %d instead)",
   118         qWarning("[hbsplash] Image format for %s is not ARGB32_PRE (is %d instead)",
   107                  qPrintable(f.mFullName), fmt);
   119                  qPrintable(f.mFullName), fmt);
       
   120     }
       
   121     if (fmt < 0 || fmt >= QImage::NImageFormats) {
       
   122         qWarning("[hbsplash] Image format is invalid");
       
   123         return 0;
   108     }
   124     }
   109     qint64 sz = h * bpl;
   125     qint64 sz = h * bpl;
   110     uchar *data = 0;
   126     uchar *data = 0;
   111     if (w > 0 && h > 0 && bpl > 0 && sz > 0 && sz <= image_bytes_limit) {
   127     if (w > 0 && h > 0 && bpl > 0 && sz > 0 && sz <= image_bytes_limit) {
   112         try {
   128         try {
   114                 data = params.allocFunc(w, h, bpl, fmt, params.allocFuncParam);
   130                 data = params.allocFunc(w, h, bpl, fmt, params.allocFuncParam);
   115             } else {
   131             } else {
   116                 data = new uchar[sz];
   132                 data = new uchar[sz];
   117             }
   133             }
   118             if (data) {
   134             if (data) {
   119                 qint64 bytesRead = f.read((char *) data, sz);
   135                 qint64 bytesRead = f.read(reinterpret_cast<char *>(data), sz);
   120                 if (bytesRead != sz) {
   136                 if (bytesRead != sz) {
   121                     qWarning("HbSplash: file %s is invalid", qPrintable(f.mFullName));
   137                     qWarning("[hbsplash] File %s is invalid", qPrintable(f.mFullName));
   122                     if (!params.allocFunc) {
   138                     if (!params.allocFunc) {
   123                         delete data;
   139                         delete[] data;
   124                     }
   140                     }
   125                     data = 0;
   141                     data = 0;
   126                 }
   142                 }
   127             }
   143             }
   128         } catch (const std::bad_alloc &) {
   144         } catch (const std::bad_alloc &) {
   129             qWarning("HbSplash: failed to allocate image buffer");
   145             qWarning("[hbsplash] Failed to allocate image buffer");
   130         }
   146         }
   131     } else {
   147     } else {
   132         qWarning("HbSplash: image in file %s is too big", qPrintable(f.mFullName));
   148         qWarning("[hbsplash] Image in file %s is too big", qPrintable(f.mFullName));
   133     }
   149     }
   134     *params.w = w;
   150     *params.w = w;
   135     *params.h = h;
   151     *params.h = h;
   136     *params.bpl = bpl;
   152     *params.bpl = bpl;
   137     *params.fmt = fmt;
   153     *params.fmt = fmt;
   138     return data;
   154     return data;
   139 }
   155 }
   140 
   156 
   141 #ifdef Q_OS_SYMBIAN
   157 #ifdef Q_OS_SYMBIAN
   142 
   158 
       
   159 // Symbian-specific implementation to get splash screens either by
       
   160 // reading from a file opened on the server side or by using bitmaps
       
   161 // shared via fbserv.
       
   162 
   143 class HbSplashSrvClient : public RSessionBase
   163 class HbSplashSrvClient : public RSessionBase
   144 {
   164 {
   145 public:
   165 public:
   146     HbSplashSrvClient();
   166     HbSplashSrvClient();
   147     ~HbSplashSrvClient();
   167     ~HbSplashSrvClient();
   148     bool Connect();
   168     bool Connect();
   149     bool getSplash(RFile &f, const QString &ori, const QString &appId, const QString &screenId);
   169 
       
   170     bool getSplashFileHandle(RFile &f,
       
   171                              const QString &ori,
       
   172                              const QString &appId,
       
   173                              const QString &screenId);
       
   174 
       
   175     uchar *getSplashFromBitmap(const QString &ori,
       
   176                                const QString &appId,
       
   177                                const QString &screenId,
       
   178                                Params &params);
       
   179 
   150 private:
   180 private:
   151     RMutex mMutex;
   181     RMutex mMutex;
   152     bool mMutexOk;
   182     bool mMutexOk;
   153 };
   183 };
   154 
   184 
   183         TInt err = CreateSession(hbsplash_server_name, ver);
   213         TInt err = CreateSession(hbsplash_server_name, ver);
   184         qDebug("[hbsplash] CreateSession result: %d", err);
   214         qDebug("[hbsplash] CreateSession result: %d", err);
   185         if (err == KErrNone) {
   215         if (err == KErrNone) {
   186             ok = true;
   216             ok = true;
   187             break;
   217             break;
   188 /*
       
   189         } else if (err == KErrNotFound || err == KErrServerTerminated) {
   218         } else if (err == KErrNotFound || err == KErrServerTerminated) {
   190             qDebug("[hbsplash] Server not running");
   219             qDebug("[hbsplash] server not running");
   191             TFindServer findServer(hbsplash_server_name);
   220             TFindServer findServer(hbsplash_server_name);
   192             TFullName name;
   221             TFullName name;
   193             if (findServer.Next(name) != KErrNone) {
   222             if (findServer.Next(name) != KErrNone) {
   194                 RProcess server;
   223                 RProcess server;
   195                 const TUidType uid(KNullUid, KNullUid, hbsplash_server_uid3);
   224                 const TUidType uid(KNullUid, KNullUid, hbsplash_server_uid3);
   209                 server.Close();
   238                 server.Close();
   210                 if (status.Int() != KErrNone && status.Int() != KErrAlreadyExists) {
   239                 if (status.Int() != KErrNone && status.Int() != KErrAlreadyExists) {
   211                     qWarning("[hbsplash] Rendezvous failed (%d)", status.Int());
   240                     qWarning("[hbsplash] Rendezvous failed (%d)", status.Int());
   212                     break;
   241                     break;
   213                 }
   242                 }
   214                 qDebug("[hbsplash] Server started");
   243                 qDebug("[hbsplash] server started");
   215             }
   244             }
   216 */
       
   217         } else {
   245         } else {
   218             break;
   246             break;
   219         }
   247         }
   220     }
   248     }
   221     if (!ok) {
   249     if (!ok) {
   222         qWarning("[hbsplash] cannot connect to splashgen server");
   250         qWarning("[hbsplash] Cannot connect to splashgen server");
   223     }
   251     }
   224     if (mMutexOk) {
   252     if (mMutexOk) {
   225         mMutex.Signal();
   253         mMutex.Signal();
   226     }
   254     }
   227     return ok;
   255     return ok;
   228 }
   256 }
   229 
   257 
   230 bool HbSplashSrvClient::getSplash(RFile &f, const QString &ori,
   258 bool HbSplashSrvClient::getSplashFileHandle(RFile &f,
   231                                   const QString &appId, const QString &screenId)
   259         const QString &ori,
       
   260         const QString &appId,
       
   261         const QString &screenId)
   232 {
   262 {
   233     TPtrC oriDes(static_cast<const TUint16 *>(ori.utf16()), ori.length());
   263     TPtrC oriDes(static_cast<const TUint16 *>(ori.utf16()), ori.length());
   234     TPtrC appIdDes(static_cast<const TUint16 *>(appId.utf16()), appId.length());
   264     TPtrC appIdDes(static_cast<const TUint16 *>(appId.utf16()), appId.length());
   235     TPtrC screenIdDes(static_cast<const TUint16 *>(screenId.utf16()), screenId.length());
   265     TPtrC screenIdDes(static_cast<const TUint16 *>(screenId.utf16()), screenId.length());
   236     TInt fileHandle;
   266     TInt fileHandle;
   237     TPckg<TInt> fileHandlePckg(fileHandle);
   267     TPckg<TInt> fileHandlePckg(fileHandle);
   238     TIpcArgs args(&oriDes, &appIdDes, &screenIdDes, &fileHandlePckg);
   268     TIpcArgs args(&oriDes, &appIdDes, &screenIdDes, &fileHandlePckg);
   239     TInt fsHandle = SendReceive(HbSplashSrvGetSplash, args);
   269     TInt fsHandle = SendReceive(HbSplashSrvGetSplashFile, args);
   240     return f.AdoptFromServer(fsHandle, fileHandle) == KErrNone;
   270     return f.AdoptFromServer(fsHandle, fileHandle) == KErrNone;
   241 }
   271 }
   242 
   272 
   243 static uchar *load_symbian(const Params &params)
   273 uchar *HbSplashSrvClient::getSplashFromBitmap(const QString &ori,
       
   274         const QString &appId,
       
   275         const QString &screenId,
       
   276         Params &params)
       
   277 {
       
   278     TPtrC oriDes(static_cast<const TUint16 *>(ori.utf16()), ori.length());
       
   279     TPtrC appIdDes(static_cast<const TUint16 *>(appId.utf16()), appId.length());
       
   280     TPtrC screenIdDes(static_cast<const TUint16 *>(screenId.utf16()), screenId.length());
       
   281     TInt bitmapHandle;
       
   282     TPckg<TInt> bitmapHandlePckg(bitmapHandle);
       
   283     TIpcArgs args(&oriDes, &appIdDes, &screenIdDes, &bitmapHandlePckg);
       
   284     if (SendReceive(HbSplashSrvGetSplashData, args) == KErrNone) {
       
   285         QScopedPointer<CFbsBitmap> bmp(new CFbsBitmap);
       
   286         if (bmp->Duplicate(bitmapHandle) == KErrNone) {
       
   287             TSize size = bmp->SizeInPixels();
       
   288             TDisplayMode mode = bmp->DisplayMode();
       
   289             if (size.iWidth > 0 && size.iHeight > 0 && mode == EColor16MAP) {
       
   290                 int bpl = CFbsBitmap::ScanLineLength(size.iWidth, mode);
       
   291                 const QImage::Format fmt = QImage::Format_ARGB32_Premultiplied;
       
   292                 int len = bpl * size.iHeight;
       
   293                 uchar *data = 0;
       
   294                 try {
       
   295                     if (params.allocFunc) {
       
   296                         data = params.allocFunc(size.iWidth, size.iHeight,
       
   297                                                 bpl, fmt, params.allocFuncParam);
       
   298                     } else {
       
   299                         data = new uchar[len];
       
   300                     }
       
   301                     if (data) {
       
   302                         memcpy(data, bmp->DataAddress(), len);
       
   303                         *params.w = size.iWidth;
       
   304                         *params.h = size.iHeight;
       
   305                         *params.bpl = bpl;
       
   306                         *params.fmt = fmt;
       
   307                         qDebug("[hbsplash] bitmap data received");
       
   308                         return data;
       
   309                     }
       
   310                 } catch (const std::bad_alloc &) {
       
   311                     qWarning("[hbsplash] Failed to allocate image buffer");
       
   312                 }
       
   313             } else {
       
   314                 qWarning("[hbsplash] Invalid bitmap (%d %d %d)",
       
   315                          size.iWidth, size.iHeight, mode);
       
   316             }
       
   317         } else {
       
   318             qWarning("[hbsplash] Cannot duplicate bitmap");
       
   319         }
       
   320     }
       
   321     return 0;
       
   322 }
       
   323 
       
   324 static uchar *load_symbian(Params &params)
   244 {
   325 {
   245     HbSplashSrvClient client;
   326     HbSplashSrvClient client;
   246     if (!client.Connect()) {
   327     if (!client.Connect()) {
   247         return false;
   328         return false;
   248     }
   329     }
   250     QString oriStr(orientationId(params.flags));
   331     QString oriStr(orientationId(params.flags));
   251     QString appIdStr(params.appId);
   332     QString appIdStr(params.appId);
   252     if (appIdStr.isEmpty()) {
   333     if (appIdStr.isEmpty()) {
   253         RProcess process;
   334         RProcess process;
   254         appIdStr = QString::number(process.SecureId().iId, 16);
   335         appIdStr = QString::number(process.SecureId().iId, 16);
       
   336         process.Close();
   255     }
   337     }
   256 
   338 
   257     uchar *data = 0;
   339     uchar *data = 0;
   258     File f;
   340     if (!params.forceFile) {
   259     f.mFullName = "[unavailable]";
   341         data = client.getSplashFromBitmap(oriStr, appIdStr, params.screenId, params);
   260     if (client.getSplash(f.mFile, oriStr, appIdStr, params.screenId)) {
   342     } else {
   261         qDebug("[hbsplash] got handle from server");
   343         File f;
   262         data = readSpl(f, params);
   344         f.mFullName = "[unavailable]";
   263         f.mFile.Close();
   345         if (client.getSplashFileHandle(f.mFile, oriStr, appIdStr, params.screenId)) {
       
   346             qDebug("[hbsplash] got handle from server");
       
   347             data = readSpl(f, params);
       
   348             f.mFile.Close();
       
   349         }
   264     }
   350     }
   265 
   351 
   266     client.Close();
   352     client.Close();
   267     return data;
   353     return data;
   268 }
   354 }
   269 
   355 
   270 #else
   356 #else
   271 
   357 
   272 static uchar *read_file_generic(const QString &name, const Params &params)
   358 // Generic cross-platform implementation, reads the pixel data
       
   359 // directly from files. Not suitable for Symbian due to platsec and
       
   360 // performance reasons.
       
   361 
       
   362 static uchar *read_file_generic(const QString &name, Params &params)
   273 {
   363 {
   274     uchar *data = 0;
   364     uchar *data = 0;
   275     File f;
   365     File f;
   276     f.mFullName = name;
   366     f.mFullName = name;
   277     f.mFile.setFileName(name);
   367     f.mFile.setFileName(name);
   280         f.mFile.close();
   370         f.mFile.close();
   281     }
   371     }
   282     return data;
   372     return data;
   283 }
   373 }
   284 
   374 
   285 static uchar *load_generic(const Params &params)
   375 static uchar *load_generic(Params &params)
   286 {
   376 {
   287     QString appSpecificName("splash_%1_%2.spl");
   377     QString appSpecificName("splash_%1_%2.spl");
   288     QString appAndScreenSpecificName("splash_%1_%2_%3.spl");
   378     QString appAndScreenSpecificName("splash_%1_%2_%3.spl");
   289     QString genericName("splash_%1.spl");
   379     QString genericName("splash_%1.spl");
   290     QDir dir("splashscreens"); // see hbsplashgenerator
   380     QDir dir("splashscreens"); // see hbsplashgenerator
   359     params.flags = flags;
   449     params.flags = flags;
   360     params.appId = appId;
   450     params.appId = appId;
   361     params.screenId = screenId;
   451     params.screenId = screenId;
   362     params.allocFunc = allocFunc;
   452     params.allocFunc = allocFunc;
   363     params.allocFuncParam = allocFuncParam;
   453     params.allocFuncParam = allocFuncParam;
       
   454     params.forceFile = false; // use CFbsBitmap-based sharing on Symbian
   364 #ifdef Q_OS_SYMBIAN
   455 #ifdef Q_OS_SYMBIAN
   365     return load_symbian(params);
   456     return load_symbian(params);
   366 #else
   457 #else
   367     return load_generic(params);
   458     return load_generic(params);
   368 #endif
   459 #endif
   369 }
   460 }
       
   461 
       
   462 #ifdef Q_OS_SYMBIAN
       
   463 static uchar *fbsBitmapAllocFunc(int w, int h, int bpl, QImage::Format fmt, void *param)
       
   464 {
       
   465     if (fmt != QImage::Format_ARGB32_Premultiplied) {
       
   466         qWarning("[hbsplash] fbsBitmapAllocFunc: unsupported format %d", fmt);
       
   467         return 0;
       
   468     }
       
   469     TDisplayMode mode = EColor16MAP;
       
   470     CFbsBitmap *bmp = static_cast<CFbsBitmap *>(param);
       
   471     if (bmp->Create(TSize(w, h), mode) == KErrNone) {
       
   472         int bmpBpl = CFbsBitmap::ScanLineLength(w, mode);
       
   473         if (bpl == bmpBpl) {
       
   474             return reinterpret_cast<uchar *>(bmp->DataAddress());
       
   475         } else {
       
   476             qWarning("[hbsplash] fbsBitmapAllocFunc: bpl mismatch (%d - %d)", bpl, bmpBpl);
       
   477         }
       
   478     } else {
       
   479         qWarning("[hbsplash] fbsBitmapAllocFunc: bitmap Create() failed");
       
   480     }
       
   481     return 0;
       
   482 }
       
   483 #endif
       
   484 
       
   485 void *HbSplashDirectSymbian::load(void *file, int *extra)
       
   486 {
       
   487 #ifdef Q_OS_SYMBIAN
       
   488     // Read the data directly into a CFbsBitmap. `file' is assumed to
       
   489     // be a ptr to an already Open()'ed RFile.
       
   490     QScopedPointer<CFbsBitmap> bmp(new CFbsBitmap);
       
   491     int w, h, bpl;
       
   492     QImage::Format fmt;
       
   493     Params params;
       
   494     // Everything is ignored except the alloc-func and its param.
       
   495     params.w = &w;
       
   496     params.h = &h;
       
   497     params.bpl = &bpl;
       
   498     params.fmt = &fmt;
       
   499     params.flags = HbSplashScreen::Default;
       
   500     params.allocFunc = fbsBitmapAllocFunc;
       
   501     params.allocFuncParam = bmp.data();
       
   502     File f;
       
   503     f.mFile = *static_cast<RFile *>(file);
       
   504     if (readSpl(f, params)) {
       
   505         if (extra) {
       
   506             *extra = params.extra;
       
   507         }
       
   508         return bmp.take();
       
   509     }
       
   510 #else
       
   511     Q_UNUSED(file);
       
   512     Q_UNUSED(extra);
       
   513 #endif
       
   514     return 0;
       
   515 }