Thursday, July 28, 2011

Audiobook reader New Features, Chapter selection and custom Bookmark support added

Today my next version of Audiobook reader application got published on Ovi Store. This version include some new feature with some other impoverishment.

New feature are as below,

  • Chapter Selection, If Audiobook has multiple audio file for individual chapter then now you can select and play individual chapter.
  • Custom Bookmark support, In case Audiobook is one large audio file and you found some interesting chapter then you can add bookmark, Bookmark will save play position. Latter if you wish to hear that chapter, you can go to bookmark screen and play that bookmark.
Both bookmark and chapter selection feature are available from main Booklist screen. In following snap, by pressing icon next to play icon will lead you to bookmark/ chapter screen.


Following is Chapter/Bookmark Screen. By pressing Icon next to back icon, will show chapter or bookmark screen.

In following snaps is showing chapter screen. On this screen if you press book icon, it will switch screen to bookmark screen.


Following snap is showing Bookmark screen, by pressing list icon you can switch back to Chapter Screen.


You can add custom bookmark from player screen, by pressing + icon and then entering bookmark name on Add Bookmark dialog.



Hope you will like this new feature, If you have any comment please feel free to add comment.

Saturday, July 23, 2011

Simple download manager with pause support implementation

In one of my previous post, I described how a simple download manage with pause/ resume feature can be implemented. Here is post.

After that post I got few request for further explanation or working code sample. So in this post I will describe implementation in more details and provide full working code sample.

I lost older working code because of my laptop crash, so created another sample application for this post, so code might differ a little bit from my older post, but idea is same.

So here code the code.

Following is download function where download request is placed by client.
void DownloadManager::download( QUrl url )
{
    mDownloadSizeAtPause =0;
    mCurrentRequest = QNetworkRequest(url);
    mFile = new QFile("download.part");
    mFile->open(QIODevice::ReadWrite);

    download(mCurrentRequest);
}

Following function put download request to QNetworkAccessManager and setup signal slot connection.
void DownloadManager::download( QNetworkRequest& request )
{
    mCurrentReply = mManager->get(request);

    connect(mCurrentReply,SIGNAL(finished()),this,SLOT(finished()));
    connect(mCurrentReply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(downloadProgress(qint64,qint64)));
    connect(mCurrentReply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(error(QNetworkReply::NetworkError)));
}

Now the interesting functions comes that enable pause/resume functionality to download manager. Following is pause function. If simply abort current request, disconnect the signal/slot so we don't get any error signal and mess with our error handling code and most importantly it write data to our IODevice here its file which is storing downloaded data.
void DownloadManager::pause()
{
    if( mCurrentReply == 0 ) {
        return;
    }
    disconnect(mCurrentReply,SIGNAL(finished()),this,SLOT(finished()));
    disconnect(mCurrentReply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(downloadProgress(qint64,qint64)));
    disconnect(mCurrentReply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(error(QNetworkReply::NetworkError)));

    mCurrentReply->abort();
    mFile->write( mCurrentReply->readAll());
    mCurrentReply = 0;
}

Now the resume function. So most important thing here is "Range" header. It tell the server that I want to start download from this much bytes and not from beginning, because we already received this much data when we paused the request.

void DownloadManager::resume()
{
    mDownloadSizeAtPause = mFile->size();
    QByteArray rangeHeaderValue = "bytes=" + QByteArray::number(mDownloadSizeAtPause) + "-";
    mCurrentRequest.setRawHeader("Range",rangeHeaderValue);

    download(mCurrentRequest);
}

Another important function, if you want to show correct progress. Remember to add mDownloadSizeAtPause (number of bytes already downloded when we pause the request ) to bytesReceived and bytesTotal, function to show correct progress.
void DownloadManager::downloadProgress ( qint64 bytesReceived, qint64 bytesTotal )
{
    mFile->write( mCurrentReply->readAll() );
    int percentage = ((mDownloadSizeAtPause+bytesReceived) * 100 )/ (mDownloadSizeAtPause+bytesTotal);
    emit progress(percentage);
}

here is link to full working sample project. Thank you for visiting my blog. Let me know if you need more details.

Sunday, July 17, 2011

Swipe to unlock animation effect using QML

Now its raining heavily here and that provided me some free time to play with my iPod. As I was using my iPod I got curious about how that "swipe to unlock" animation could have been implemented.

I decided to implement such animation my self with QML and following is output of my effort.



If you also curious about how it can be implemented, than solution is quite simple.
The code is similar to code for Marquee text animation. To give marquee text effect, I used to change position of text element only. Here I change position of both text and parent Item element.

Here is full code. In code I created one static text in gray color which is fully visible and another text with white color which is partially visible only ans used for scrolling animation. I put this animating text inside Item element.

Now on timer event, I am increasing x position of Item element with some delta , at same time I am also reducing same delta from text x position. This will give effect as color or gray static text is changing.

import QtQuick 1.0

Item {
    id:marqueeText
    height: staticText.height
    clip: true    
    property int tempX: 0
    property alias text: staticText.text
    Text {
        x:0;y:0        
        id:staticText
        width: marqueeText.width
        color: "darkgray"
    }

    Item {
        width: 40
        height: marqueeText.height
        x: tempX
        clip: true
        Text {
            id:scrollingText
            text: marqueeText.text
            color: "white"
        }
    }

    Timer {
        id:timer
        interval: 200; running: true; repeat: true
        onTriggered:{            
            tempX = tempX + 10
            scrollingText.x = -tempX;

            if( tempX > staticText.width ) {
                tempX=-40
            }
        }
    }
}
Here is how above code can be used.
Rectangle {
        border.width: 2
        border.color: "black"
        color:"gray"
        anchors.horizontalCenter: parent.horizontalCenter
        width: 200
        height: text.height + 10
        y:100
        ScrollText {
            id:text
            width: 150
            anchors.verticalCenter: parent.verticalCenter
            anchors.horizontalCenter: parent.horizontalCenter
            text: "Swipe to unlock the phone"
        }
    }

That's all. Hope you enjoyed it.

Saturday, July 16, 2011

My new 3D Plasma HD TV (Samsung PN43D490A1D-S)

Recently I purchased Samsung 43 inch 3d Plasma tv (PN43D490A1D-S). Its entry level model thus I got only one 3d shutter glass model(SSG-3500CR).

I have tried 2-3 shutter glasses from Samsung and I feel that glasses which I got with TV put less strain on eyes and don't feel flicker of LCD of shutter glasses with this model.


As soon as I got it, I tried to play some HD content on it and result looks great from 4-5 feet distance.

It got one USB port and 3 HDMI port. We can plug USB drive and play video from it. You need to select USB drive as input source and then it will show file manager and there you can browse for content. It has inbuilt movie player. Which play movie from USB drive. I tried to use this inbuilt media player and found it quite nice and useful. It recognize many video format include mp4  and divx. I also tried some mkv file which has dual audio support. It can play that source as well and allow to change language.

Now that I tried 2D content,  I wanted to try some 3d content.

To watch 3d content,I connected my laptop via HDMI cable and made my tv primary monitor then played some 3d content from youtube.

It took me quite some time to figure out that, that to watch 3d content from 3d tv. I need to play video that is in half side by side (half sbs) format other kind of video want give 3d effect with 3d tv with shutter technology.

After starting half sbs movie, you need change to 3D mode from 2D and select side by side format. Now put on glasses and can enjoy 3D content.





After playing 3D content from my laptop, I downloaded some sample half SBS 3D content and tied to play it with its inbuilt media player. I feel that content looks great on inbuilt player than from PC.

Thats all now I am going to watch some moive on my new Tv. Thanks for reading.

Tuesday, July 5, 2011

How to display QWidget into QML

Recently in one of my project I required to embed QWidget derived class to QML scene. While its straight forward to embed QML scene to QWidget or QGraphicsScene.

It required small effort to embed QWidget derived class to QML scene. Still its not great effort and its also vary straigt forward.

All you need to do is, create new class derived from QDeclarativeItem. Create instance of required widget and add that widget to QGraphicsProxyWidget. Now we need to register this newly created class to QML using qmlRegisterType. Now we can use this class from QML which display our QWidget derived class.

Following is code that demonstrate the same. For demo I have created class which embed QLabel to QML scene.

Following code is my custom QDeclarativeItem derive class which will expose QLabel to QML scene.
#include <QDeclarativeItem>

class QLabel;

class QmlLabel : public QDeclarativeItem
{
    Q_OBJECT    
    Q_PROPERTY(QString text READ text WRITE setText)
public:
    explicit QmlLabel(QDeclarativeItem *parent = 0);
    ~QmlLabel();    

public slots:

    void setText(const QString& text);

    QString text() const;

private:

    QLabel* mLabel;
    QGraphicsProxyWidget* mProxy;

};

#include <QLabel>
#include <QGraphicsProxyWidget>

QmlLabel::QmlLabel(QDeclarativeItem *parent) :
    QDeclarativeItem(parent)
{
    mLabel = new QLabel(QString(""));
    mProxy = new QGraphicsProxyWidget(this);
    mProxy->setWidget(mLabel);
}

QmlLabel::~QmlLabel()
{
    delete mLabel;
}

void QmlLabel::setText(const QString& text)
{
    mLabel->setText(text);
}

QString QmlLabel::text() const
{
    return mLabel->text();
}

Following code demonstrate how to register above class to QML. In qmlRegisterType first argument is component uri, which is used for importing component to QML. second and third argument is version information and fourth argument is element name in QML, By using this name we can created QML element.

#include <QtDeclarative>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    qmlRegisterType<QmlLabel>("qmlLabel", 1, 0, "QmlLabel");
    QDeclarativeView viewer;
    viewer.setSource(QUrl("qml/hybrid/main.qml"));
    viewer.show();
    return app.exec();
}

Finally following is QML code. To be able to use our custom QML element we need to import component to QML using import statement.
import QtQuick 1.0
import qmlLabel 1.0

Rectangle {
    width: 360
    height: 360
    QmlLabel {         
        x:100; y:100
        text: "QML Label"
    }
}

Following is out put from above code.