Finally in the store!

November 10, 2011 at 9:07 am | Posted in Uncategorized | Leave a comment

The Morse Player has finally gone into the store after several attempts. The biggest problem stopping the application from being accepted was the “equally functional in portrait and landscape mode” requirement.

Originally, this was solved, but then I put in a Morse Code table as an QML splash screen and as a menu item. This had rotation problems, performance problems, and then rendering problems. And this was an eye candy feature – mainly the version/web page information plus additional information for learning morse.

The rotation problem was due to the method to present the morse code table, it was 3 columns that went off the screen in landscape, so this had to be changed – leading a performance problem. This issue came from my use of loaders to change the morse code table between portrait and landscape (I just wanted to try them out really). Creating both the portrait and landscape tables, making them invisible/visible depending on the screen orientation solved the performance, leaving only the rendering issue.

The rendering issue came from the use of a completely black background in the morse table in a application with a white background. When static this did not cause any problems, but when rotating the display white lines flickered at the top of the display. I presume this comes from the application background getting rendered first. After some hacking, the solution I chose was to invert the application when showing the morse table and rotating. This solved the issue, maybe not the cleanest solution, but it worked.

This simple morse code table feature also forced me to play with showing the status bar when in landscape mode. Removing the status bar gives more screen, and in the landscape mode height is a value resource.
Again, this caused me to dig some more to get a reliable way of working out when the application is in landscape mode. The first approach was to use the QML PageStackWindow inPortrait property, but when the virtual keyboard is shown this becomes undefined. This makes sense because when the keyboard is shown the application is in neither landscape or portrait modes. The solution is to use the Screen object’s orientation policy, as described in the developer.nokia.com wiki. This is pretty reliable and works whether the virtual keyboard is active or not, at it is very easy:

main.qml:

...
onOrientationChangeFinished: {
  appWindow.showStatusBar = 
    ( ( screen.currentOrientation == Screen.Portrait ) || 
      ( screen.currentOrientation == Screen.PortraitInverted ) );
}
...

The source code of the accepted application is here.
http://www.developer.nokia.com/Community/Wiki/File:Morseplayer_0_0_7.tar.gz

If you want to check out the application just search on the Nokia Store for morse.

Now all I need is some more real features……

Bugs, bugs, and then some features…

October 13, 2011 at 8:34 am | Posted in Uncategorized | Leave a comment

Well, needless to say the quick submission to Ovi Store did not work. There were bugs that needed to be corrected:

1. The Qt SDK overwrote the qmlapplicationviewer.cpp code at the last build so the application did not show any QML.
2. The playing of morse code disabled the UI, creating a warning message.
3. When rotating the device while inputing text the playbutton took over the entire screen.
4. (This one I found myself), there is need for about information so this needed to be added.

So back to the SDK to clean things up.

The first bug is easy to fix as I just started using code version control – a quick revert and we’re done.

The second bug is much more tricky. My first idea was to use a WorkerScript inside my existing QML code to run the morse playback. This was a mistake, as it seems there is no way to access a QML object from within a WorkerScript (especially a C++ object). So the way forward was to insert the threading into the MorsePlayer C++ object. As a side-effect I was able to include a stop functionality, so a user can stop morse playback.

morseplayer.cpp:

...
class MorseThread : public QThread {

public:
    MorseThread ( MorsePlayer* player ) : 
          m_player( player ), m_text( "" ), 
          m_stop(false), m_mutex() {}

    void setText( const QString& text ) { m_text = text; }

    void run() {
        m_stop = false;
        QString morseString( m_text.toUpper() );
        m_player->setSending( true );
        for ( int i = 0; i playLetter( morseString.at( i ) );
            QMutexLocker locker(&m_mutex);
            if ( m_stop ) {
                break;
            }
        }
        m_player->setSending( false );
    }
public slots:
    void stopFlag( bool stopFlagValue ) {
        QMutexLocker locker(&m_mutex);
        m_stop = stopFlagValue;
    }

public:
    MorsePlayer* m_player;
    QString m_text;
    bool m_stop;
    QMutex m_mutex;
};
...

The third bug was also tricky. After trying to detect rotation using the Window orientationChangeFinished signal, and noticing that the virtual keyboard interferes with the result, the method I chose was to remove the button when the TextArea was active – this improves the usability as it is unlikely a user will want to input and playback at the same time. This also gave me a chance to play around with QML animations, and states.

MainPage.qml:

...
   Behavior on height { PropertyAnimation { duration: 500 } }
   Behavior on font.pixelSize { PropertyAnimation { duration: 500 } }
   states: [
     State {
       name: "active"
       when: morseText.activeFocus
       PropertyChanges {
         target: playButton
         height: 0
       }
       PropertyChanges {
         target: playButton
         font.pixelSize: 1
       }
     },
     State {
       name: "inactive"
       when: !morseText.activeFocus
       PropertyChanges {
         target: playButton
         height: ( parent.height*0.2 )
       }
       PropertyChanges {
         target: playButton
         font.pixelSize: ( parent.height*0.1 )
       }
    }
  ]
...

The last bug was interesting too. Just for the fun of it I decided to make a QML splash screen and to reuse it inside the application. This meant I had to play around with the application’s page stack.

main.qml:

...
  initialPage: SplashScreen {
    id: splashPage
    Timer {
      id: timer
      interval: 300
      running: true
      onTriggered: {
        var component = 
          Qt.createQmlObject( 'import QtQuick 1.1; MainPage { }', 
          appWindow );
        appWindow.pageStack.push( component );
      }
    }
  }
...

To activate the about screen from within the application I added a toolbar, and got hit by a gotcha. The final code:

main.qml:

...
  ToolBarLayout {
    id: commonTools
    visible: false
    ToolIcon {
      platformIconId: "toolbar-view-menu"
      anchors.right: (parent === undefined) ? undefined : parent.right
      onClicked: {
        var component = 
          Qt.createQmlObject( 
          'import QtQuick 1.1; SplashScreen { tools: backgroundTools }',
                   appWindow );
        appWindow.pageStack.push( component )
      }
   }
  }

  ToolBarLayout {
    id: backgroundTools
    visible: false
    ToolIcon {
      platformIconId: "toolbar-back"
      anchors.left: (parent === undefined) ? undefined : parent.left
      onClicked: {
        appWindow.pageStack.pop();
       }
    }
  }
...

The gotcha is to make the toolbars invisible in the PageStackWindow, and only to enable them in the Page code using tools property.

I also heard that it is possible to create another splash screen using the Nokia N9 program (see “Enabling a splash screen for an application”). This requires images 854×480, so out with the GIMP program and following the Drive application approach I created two images with the MP logo. The next step is to hack the _harmattan.desktop file:

...
Exec=/usr/bin/invoker --type=d --splash=/opt/morseplayer/morseplayer_portraitSplash.png 
                     --splash-landscape=/opt/morseplayer/morseplayer_landscapeSplash.png 
                     -s /opt/morseplayer/bin/morseplayer
...

Now it is time to re-submit.
(The updated source code is here.)

Simple Morse Player for the N950, now for the N9 and submitted to Store.

October 4, 2011 at 3:27 pm | Posted in Uncategorized | Leave a comment

Store Submission done!

Well, I thought I would share my code with the world by putting the application on the Nokia Store. This was pretty easy once I had cleaned up the code a bit.

The big thing for me was placing the qml files inside the binary. The files where put inside a resource file, and the QmlApplicationViewer setMainQmlFile function hacked to remove the adjustPath function call, and to use a QUrl instead of a local file.

void QmlApplicationViewer::setMainQmlFile(const QString &file)
{
    d->mainQmlFile = file;
    d->view->setSource(QUrl(d->mainQmlFile));
}

Then the main.cpp needed to be changed to point to the resource file;

...
    viewer->setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
    viewer->setMainQmlFile("qrc:/qml/qml/morseplayer/main.qml");
    viewer->showExpanded();
...

Additionally, I created a configuration file for linking the application to the resource management framework:

[classify media]
/opt/morseplayer/bin/morseplayer

And altered the .pro file to install this file into the right location on the device:

...
contains(MEEGO_EDITION,harmattan) {
    desktopfile.files = $${TARGET}.desktop
    desktopfile.path = /usr/share/applications
    rsrc_config.files = morseplayer.conf
    rsrc_config.path = /usr/share/policy/etc/syspart.conf.d
    INSTALLS += desktopfile rsrc_config
}
...

To make things proper I also did some editing to the debian packaging tools, see the source code for more information.

Once the software was ready, it was time to put it in the Store. So after quickly running through the quality criteria, I started the publish process.

For those of you who will do this later, you will need a screenshot in two formats square, and in the N9 resolution. I created the screenshot using the screenshot tool, and then made it square using GIMP. The Store also wants a 256×256 icon, this I created using GIMP and scaling up the application icon.

The rest of the information is pretty straightforward:
1. A web site (this blog)
2. A maintainer email (my own)

And then it is there.
Here is the source code.

Now all I have to do is wait for Store QA to get back to me.

Simple morse player for the N950

September 26, 2011 at 9:56 am | Posted in Software Development, Uncategorized | Leave a comment

Remember the old fashioned movies with spies and sailors going dit-dit-dah to each other. Well now you can relive that nostalgia with the “Morse Code Player (source code available below).

This application was supposed to be a quickie that just does a few simple things, but in the end it turned out to be a headache due to my limited understanding of the threading behaviour of QML and Qt C++. The core of the application consists of two C++ classes the MorsePlayer that converts text to morse, and the ToneEngine that creates a audio tone.

The MorsePlayer class is relatively straightforward QML binding class that has a bit of logic for converting text to morse, and then for call the ToneEngine to play the necessary tone. The ToneEngine class is a bit more complicated; it copies logic from the AudioOutput example for generating a simple tone. The tricky bit (that took several half days to solve) was working out that the audio handling code (ToneGenerator, QAudioOutput) needs to run in its own thread, with its own event handler othwerwise the audio output blocks. Additionally. MorsePlayer needs to send signals to the ToneEnginer otherwise the audio blocks. Another tricky bit is the use of resume and suspend to start/stop the audio output, this is simply because QAudioOutput start/stop takes too long to create the initial buffers etc.

The current code is not perfect, it still occasionally has buffer underflows (any help here would be appreciated). As an application, it needs some extra features like a way to set the morse code rate, and tone frequency. Additionally, it could do with more features like haptic feedback and other clever ideas. I could also clean up the code more (add more comments, play with the design, make it a QML plugin) so I am just releasing it “as-is” as a simple example of tone generation from QML.

A simple wiki page with historical source code.

A direct link to the source tarball.

Enjoy!

Some things change, some stay the same, how painful does it have to be?

March 26, 2010 at 9:37 am | Posted in Uncategorized | Leave a comment

On Thursday Maemo Devices became Meego Devices, without any change but the name, rather surreal actually.

Not all change is progress, but progress is impossible without change.  One thing that is certain in any community change has a human and time cost, as the community adapts to the new circumstances.

So it will be with the Meego change, it will cost and benefit the people already involved in the Moblin and Maemo communities.  They will have to adjust to a new platform with a new set of technologies.  The tools they use will be different, the community management will be different, and the people they work with will be different.  All this will take some time to get used to, although the rewards are potentially huge.

Anybody who has been through a few organization changes knows the forming, storming, norming, and performing model of how a community/team adjusts to change.  The theory is that each stage is inevitable, so the issue is how to make the migration to Meego go smoothly, quickly, and with the least amount of pain, especially inside an open community?

Blog at WordPress.com.
Entries and comments feeds.