Mar 28 2010

Quasar Media Player 0.96 beta 4 available

Quasar Media Player

I am pleased to announce beta 4 of Quasar Media Player.
This new version introduces some new features and big improvements in terms of performance and memory-usage.
The previously separate last.fm Audioscrobbler QScrobbler has been integrated into Quasar as add-on.
This release also marks the introduction of the Cover Art Downloader which uses the new open-source katastrophos.net Cover Art search engine to download cover art images for the new Cover Art Flow album browser.

Quasar Media Player on Windows 7Cover Art Downloader on OS X

Binaries for the previous platforms (Sharp Qtopia and pdaXrom) along with new binaries for Windows and OS X (universal) are available on the project’s homepage.


Jul 29 2009

Nightly Builds of Quasar Media Player available

Quasar Media Player

It’s been some time since the last update. In my previous post I mentioned I was in the process of setting up a nightly build system. This system has been running silently since May.
I guess it is finally time for me to officially announce the nightly builds of Quasar Media Player:

http://www.katastrophos.net/downloads/quasar/nightly/

Along with the most current sourcecode tarball, binaries are available for 4 platforms:
Windows (win32), OS X (universal binary), Sharp Qtopia and pdaXrom Linux (both for Zaurus PDA)
The Windows version comes in two styles: a generic setup (EXE) and a self-contained portable version (7z archive)

Enjoy and please leave a comment.


Mar 16 2009

Setting up the Inno Setup compiler on Debian

I’m currently setting up a nightly build system for Quasar on my Linux box which is running Debian. This system also cross-compiles Quasar for Windows.
The Windows version of Quasar is going to be available in two fashions: one self-contained, portable version and one version that can be installed.
I’m not a huge fan of installers. But when it comes to creating a setup program for a given Windows application I’m quite accustomed to Inno Setup having used it for years. Unfortunately there is no native Linux version of the Inno Setup compiler available for Linux. NSIS exists as package for Debian but I am not fond of using it, largely because I am a Delphi guy. :)
So, here is a small guide on how to get the Inno Setup compiler up and running on Debian:

First step is to install Wine either as super user or by using sudo:

sudo apt-get install wine

As normal user fire up your X server and your favourite terminal application and get the latest Inno Setup QuickStart pack:

mkdir /tmp/innosetup
cd /tmp/innosetup
wget http://files.jrsoftware.org/ispack/ispack-5.2.3.exe
wine ./ispack-5.2.3.exe

This will start the installer in Wine. Note, for the installation you will need a running X11 server since the installer obviously is graphical. If you have not set up Wine before, the default location C:\Program Files\Inno Setup 5 will install to ~/.wine/drive_c/Programme/Inno Setup 5.

Luckily the Inno Setup compiler offers a command line interface, ISCC.exe, which will run in Wine without the necessity of having a X server running. So it is ideally suited for automated runs.

Here is a simple wrapper shell script called iscc:

#!/bin/sh
unset DISPLAY
scriptname=$1
[ -f "$scriptname" ] && scriptname=$(winepath -w "$scriptname")
wine "C:\Program Files\Inno Setup 5\ISCC.exe" "$scriptname" "$2" "$3" "$4" "$5" "$6" "$7" "$8" "$9"

I installed this script in my local bin directory (~/bin) and added it to the PATH environment variable.
This will allow running the Inno Setup compiler from anywhere and it also makes it very easy to integrate into a build script. You can even feed a script via stdin, e.g. something like:

iscc - < ./myscript.iss

Mar 15 2008

Q…/Free: Bug in QProcess writeToStdin

All right, this post is just to stop somebody else’s suffering in figuring out why writing to stdin in QProcess on Version 3.3.x-8 of Q…/Free doesn’t work on Windows. Well, actually it works but just for the first line you write to stdin. There is a bug in qprocess.cpp at line 730:

void QProcess::writeToStdin( const QString& buf )
{
    QByteArray tmp = buf.local8Bit();
    tmp.resize( tmp.size() - 1 ); // drop the implicit \0
    writeToStdin( tmp );
}

should be:

void QProcess::writeToStdin( const QString& buf )
{
    QByteArray tmp = buf.local8Bit();
    tmp.resize( buf.length() );
    writeToStdin( tmp );
}

Verision 3.3.7-7 includes the latter method, same as the latest Qt 4.3 sources. So, it’s actually a regression in 3.3.x-8. If you require the latest Qt 3 / Q…/Free for your open source application and need to write to some other processes’ stdin, you can just use a wrapper workaround that uses the latter method and directly uses writeToStdin( const QByteArray& buf ) instead of the QString variant.


Dec 24 2007

QScrobbler

QScrobbler

Today I’m releasing QScrobbler: a Last.fm / Audioscrobbler add-on for Quasar Media Player.

As with Quasar, I’ve been using QScrobbler for almost a year now and finally decided it is ready for the public. ;)
For more details please visit the project’s homepage here.


Oct 6 2007

Quasar Media Player

Quasar Media Player

Finally! Almost a year after the first mentioning of my new media player for the Sharp Zaurus and after several development hiati, I’m today officially releasing the Quasar Media Player for SharpROM- and pdaXrom-based distributions.
For more details please visit the project’s homepage here.


Jul 28 2007

“Yet Another Zaurus Media Player”… not dead yet: “Quasar Media Player”

Alright, this blog has been very quiet for the last few months. That’s partially due to me being very busy with other stuff.
I’m slowly picking up pace and getting things done again.

So, here is a short update on the media player that I’m currently developing for my Zaurus. Well, actually it’s been in long-term testing mode for ages now… :)
I finally have a name for it. It will be called “Quasar Media Player” – or shorter “Quasar”. Below are some screenshots of the current development version running on Qtopia. I hope to have a release ready soon.

{Quasar} Shown is the new toolbar and play list selector.{Quasar} The new play info screen. Cover art is supported and rendered in this funky view. Any Satch fans out there? ;){Quasar} More eyecandy.{Quasar} Normal list view filtered.


Jan 6 2007

“Yet Another Zaurus Media Player”… done differently . (Phase 2.1: Development progress 2)

Yet another short update on the development of my still untitled media player for the Zaurus. In the meantime it’s called YAZMP.

Again, I’ve been working on improving performance – this time on the performance when loading playlists.
Before I continue, let me give a brief overview of the structure:

Library -> Playlists < -> Media Cache

YAZMP doesn’t manage a library similar to i*Tunes. Instead it solely relies on playlists. Metadata (title, artist, album, etc.) is kept in the database and will be associated to once the playlist is loaded. The reason for this is pretty simple: Scanning audio files (and media files in general) each and every time a playlist is loaded will definitely take a lot of time. So, for every file the gathered metadata will be saved in the DB. Think of it as a cache.
› Continue reading


Jan 4 2007

SQLite simple timing profiler patch

Update: SQLite now features an integrated timer which can be activated via the .timer command in the console shell. Details here.

As a follow-up to my previous post “SQLite performance tuning and optimization on embedded systems” here is a very basic patch that introduces support for timing SQL queries in the sqlite3 console shell.

SQLite 3.3.8:
Patch against shell.c shell.c

SQLite 3.3.9 CVS – shell.c rev 1.157:
Patch against shell.c shell.c

Two new shell commands are introduced in sqlite3:

.profile ON|OFF        Turn profiling on or off
.timer start|show      Measure elapsed CPU time

.profile ON will turn off output to stdout. Instead it will display CPU execution time for every SQL command processed.
Here is an example output:

sqlite> .profile on
sqlite> .read test1.sql
Exec time  BEGIN;                                       :  0.000 s.
Exec time  DROP TABLE IF EXISTS playlist_view;          :  0.020 s.
Exec time  DROP TABLE IF EXISTS overview;               :  0.000 s.
Exec time  CREATE TEMPORARY TABLE playlist_view AS   ...  :  0.180 s.
Exec time  CREATE TEMPORARY TABLE overview AS        ...  :  0.140 s.
Exec time  SELECT DISTINCT genre, genre IN ("Progress...  :  0.030 s.
...

Note: You can still override the output setting with the .output command after an .profile ON has been issued.
.profile OFF will turn off time-based profiling and reenable output to stdout.

.timer start will start a timer. You can execute a sequence of queries and then print the required CPU time via .timer show.
Use .timer start again to reset the timer. This .timer patch is based on SQLite ticket #1227 by Bartosz Polednia.

Timing is currently done using clock() which provides only a 10 ms precision for CPU time on most systems. This might be inadequate depending on your requirements. If you know a more precise way, please let me know.


Jan 4 2007

SQLite performance tuning and optimization on embedded systems

Based on the experience I gained while developing my Zaurus media player, here is a short compendium of optimization rules, tweaks and hints when using SQLite on an embedded system (may apply to other systems as well):

  • Simplify the database schema as much as possible – even if that means redundant data or illogical structure
  • Don’t generalize the database schema – generalization will mostly sacrifice performance and one can’t afford that on an embedded system with its tight restrictions, even if it is more convenient for the developer.
  • Only use relations (via IDs etc.) where absolutely necessary. The overhead for lookup and joining tables is considerable, even with an index on the relation.
  • Order the tables correctly in SELECTs. Put a table left-most if it is lacking an index on the relation. More details are here.
    In general: Check the order of tables in the SELECT statement. A different permutation may be more optimal. Profile.
  • Prepare your statements and bind values where applicable. This way you can get rid of the parser and VM creation overhead in tight loops (e.g. when inserting and updating).
  • Use transactions – even if you’re just reading the data. This may yield a few milliseconds.
  • Use temporary tables for intermediate results. They are fast and stay in cache most of the time. Depending on how your SQLite instance is set up, data will only be swapped into an external file if the cache is saturated.
  • Try to avoid using views for data you’re constantly accessing. If you can afford it, create temporary tables and insert data there. This will eliminate the overhead imposed by the view evaluation.
  • Avoid sub-queries since they tend to create temporary tables and insertion of the intermediate results into those tables may be expensive.
  • Try to use indices only on static data or data that changes rarely. Building an index on live or temporary data can be expensive performance-wise. Only do so if the time required for the data lookup considerably outweights the time required for building the index.
  • Alternative to indices: hashkeys – Instead of using indices on very long strings, you may store the hash values of those strings as keys in the same table. A lookup via hash values may be a whole lot more efficient. This method is also very effective when you can’t afford the creation of an index due to performance reasons. Downside: You have to take care of the hashkeys. (See remarks in the comments below.)
  • No useless indices. Create indices only if your queries actually use the indices on the table (check with EXPLAIN). Having useless indices around may pollute otherwise precious database cache space.
  • Be cache-friendly. Depending on the memory conditions, creating temporary tables and indices may bash the cache. Reloading data back into the cache is expensive.
  • Double-check your queries and profile them. The SQLite optimizer doesn’t perform as well as the optimizers of big DBs (Firebird / Interbase, PostgreSQL, Oracle etc.).
  • Check compiler settings. A higher optimization setting in your C-compiler may very well yield a few tens of milliseconds. Make sure to inline functions (-O3 for GCC 2.95.x, -O2 for GCC 3.x.x and higher). Optimize for architecture and CPU. Omit stack frame pointers (-fomit-frame-pointer) if you’re not producing executables with debug symbols. This may free an additional register for the compiler to use.
  • Disable unused SQLite features. This helps to reduce binary size and may also affect performance.

Here are some additional docs to consider:

http://www.sqlite.org/cvstrac/wiki?p=PerformanceTuning
http://www.sqlite.org/cvstrac/wiki?p=PerformanceTuningWindows
http://www.sqlite.org/cvstrac/wiki?p=PerformanceConsiderations
http://www.sqlite.org/optoverview.html
http://web.utk.edu/~jplyon/sqlite/SQLite_optimization_FAQ.html