Friday, June 21, 2013

Inviting Application Review from Application in BB10 using Cascades API

Most time people leave a review for application when they are unhappy but if they are happy with your app, Chances are high that they will ignore the review. And this might leave impression on App World that your application if not working fine and is of low quality.

To overcome this we might offer user a option to review application from within application and some user might be happy enough to provide review.

BB10 has nice QML Cascades API, which makes the task very easy. Only few lines of code and you can have option to offer review from application.

Following is the code which I am using. You can use InvokeActionItem, with actions property of Page. "sys.appworld" this is invocation target id for App World. And in URI you need to mention your application's ID, which you can find from App World.
Page {
    ...
    actions: [
        ...
        InvokeActionItem {
            title: "Rate Application"
            ActionBar.placement: ActionBarPlacement.InOverflow
            imageSource: "rate.png"
            query {
                invokeTargetId: "sys.appworld"
                invokeActionId: "bb.action.OPEN"
                uri: "appworld://content/20200034"
            }
        }
        ...
    ]
    ...
}


Saturday, June 8, 2013

Using QML Camera and passing image to C++ code

I tried to compile one my application with Qt5. Application was using QML camera and sharing image to C++ code for further processing.

Following is sample code, it works with Qt5 and Qt Multimedia 5.

Lets start with ImageProcessor class, the C++ class which is called from QML to further image processing.

Following is header file for ImageProcessor class, it declares processImage() slot which can be invoked from QML code.
#ifndef IMAGEPROCESSOR_H
#define IMAGEPROCESSOR_H

#include <QObject>

class ImageProcessor : public QObject
{
    Q_OBJECT
public:
    explicit ImageProcessor(QObject *parent = 0);
 
public slots:
    void processImage( const QString& image);   
};
#endif // IMAGEPROCESSOR_H
Following is cpp file for ImageProcessor class. processImage() function retrieves Image from camera image provider. Once we have valid image, we can process it further.
#include "imageprocessor.h"
#include <QtQml/QmlEngine>
#include <QtQml/QmlContext>
#include <QtQuick/QQuickImageProvider>
#include <QDebug>

ImageProcessor::ImageProcessor(QObject *parent)
    : QObject(parent)
{}

void ImageProcessor::processImage( const QString& path)
{
    QUrl imageUrl(path);
    QQmlEngine* engine = QQmlEngine::contextForObject(this)->engine();
    QQmlImageProviderBase* imageProviderBase = engine->imageProvider(
     imageUrl.host());
    QQuickImageProvider* imageProvider = static_cast<QQuickImageProvider>
     (imageProviderBase);
    
    QSize imageSize;
    QString imageId = imageUrl.path().remove(0,1);
    QImage image = imageProvider->requestImage(imageId, &imageSize, imageSize);
    if( !image.isNull()) {
        //process image
    }
}
Now we need to register ImageProcessor class with QML. so that we can use it from QML code. This can be done by using qmlRegisterType global function.
#include  <QtGui/QGuiApplication>
#include  <QQmlEngine>
#include  <QQmlComponent>
#include  <QtQuick/QQuickView>

#include "imageprocessor.h"

int main(int argc, char *argv[])
{
    qmlRegisterType<ImageProcessor>("ImageProcessor", 1, 0, "ImageProcessor");

    QGuiApplication app(argc, argv);

    QQuickView view;

    QObject::connect(view.engine(),SIGNAL(quit()),&app,SLOT(quit()));    
    view.setSource(QUrl::fromLocalFile("qml/main.qml"));
    view.show();

    return app.exec();
}
That's all from C++ side, QML code is event easier. Following how you can use ImageProcess class from QML code.
import QtQuick 2.0
import QtMultimedia 5.0
import ImageProcessor 1.0

Rectangle {
    width: 360
    height: 360

    //shows live preview from camera
    VideoOutput {
        source: camera
        anchors.fill: parent
        focus : visible
    }

    //shows captured image
    Image {
        id: photoPreview
        anchors.fill: parent
        fillMode: Image.PreserveAspectFit
    }

    Camera {
        id: camera
        imageProcessing.whiteBalanceMode: CameraImageProcessing.WhiteBalanceFlash
        captureMode: Camera.CaptureStillImage

        exposure {
            exposureCompensation: -1.0
            exposureMode: Camera.ExposurePortrait
        }

        flash.mode: Camera.FlashRedEyeReduction

        imageCapture {
            onImageCaptured: {
                photoPreview.source = preview
                imageProcessor.processImage(preview);
            }
        }
    }

    MouseArea{
        anchors.fill: parent
        onClicked: {
            camera.imageCapture.capture();
        }
    }

    //image processor for further image processing
    ImageProcessor{
        id: imageProcessor
    }
}

Thursday, June 6, 2013

VMWare Workstation 9.0.1 on Ubuntu 13.04

I recently upgraded my Ubuntu machine to Ubuntu 13.04.  Update went smoothly and all my usual application worked fine. But after some time I needed to use VMWare workstation and I realized its not working any more.

I got following error.


This is caused by some header location changes. This can be resolved by following command.

sudo ln -s /usr/src/linux-headers-$(uname -r)/include/generated/uapi/linux/version.h /usr/src/linux-headers-$(uname -r)/include/linux/version.h

Once this is done, you will need to compile and install VMware modules. When I pressed install button, nothing was happening.


To check I tried to compile modules from command line.

sudo vmware-modconfig --console --install-all

But this was throwing many compilation error, anyway I found this script which make above process easier, It make link for kernel header to expected location and then build VMWare modules. You can find more details about script here.

This script seems to be working but still there was some error in driver.c file. I was getting following errors.

make[1]: Entering directory `/usr/src/linux-headers-3.8.0-23-generic'
  CC [M]  /tmp/modconfig-IBc3U5/vmci-only/linux/driver.o
  CC [M]  /tmp/modconfig-IBc3U5/vmci-only/linux/vmciKernelIf.o
  CC [M]  /tmp/modconfig-IBc3U5/vmci-only/common/vmciContext.o
  CC [M]  /tmp/modconfig-IBc3U5/vmci-only/common/vmciDatagram.o
/tmp/modconfig-IBc3U5/vmci-only/linux/driver.c:1754:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘vmci_probe_device’
/tmp/modconfig-IBc3U5/vmci-only/linux/driver.c:1982:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘vmci_remove_device’
/tmp/modconfig-IBc3U5/vmci-only/linux/driver.c:119:12: warning: ‘vmci_probe_device’ used but never defined [enabled by default]
/tmp/modconfig-IBc3U5/vmci-only/linux/driver.c:121:13: warning: ‘vmci_remove_device’ used but never defined [enabled by default]
/tmp/modconfig-IBc3U5/vmci-only/linux/driver.c:2063:1: warning: ‘vmci_interrupt’ defined but not used [-Wunused-function]
/tmp/modconfig-IBc3U5/vmci-only/linux/driver.c:2137:1: warning: ‘vmci_interrupt_bm’ defined but not used [-Wunused-function]
/tmp/modconfig-IBc3U5/vmci-only/linux/driver.c:1717:1: warning: ‘vmci_enable_msix’ defined but not used [-Wunused-function]
make[2]: *** [/tmp/modconfig-IBc3U5/vmci-only/linux/driver.o] Error 1
make[2]: *** Waiting for unfinished jobs....
make[1]: *** [_module_/tmp/modconfig-IBc3U5/vmci-only] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.8.0-23-generic'

To resolve those error you will need this kernel patch, this patch is for 3.8.0 kernel, it might not work for you. You can find more information about this patch here. To apply patch follow following steps.

1. cd /usr/lib/vmware/modules/source
2. tar -xf vmci.tar
3. cd vmci-only
4. patch -p1 < 'patchfile'
5. cd ..
6. tar -cf vmci.tar vmci-only/
7. vmware-modconfig --console --install-all
8. rm -rf vmci-only/

Once you applied above patch, VMWare module should compile fine. I ran above script, which link kernel header and build VMware module, and then I was able to use VMWare workstation.

Still there was one last hurdle, When I tried to run my virtual machine, it asked for serial number, But when I tried to enter serial number, Dialog for entering serial number was not getting launched.

To resolve those I need to supply serial number from terminal, using following command.

/usr/lib/vmware/bin/vmware-vmx --new-sn 123-123-123-123...123

Finally, I was able to use my virtual machine. I guess if you rely on virtual machine heavily, then its better to avoid Ubuntu/Kernel upgrade.