Tuesday, December 29, 2009

Amarok Bugfix and Documentation

Documentation is important/useful. I don't mean just comments in the code, I'm talking UML and perhaps written-English documentation walking through a large amount of classes. I've started to, in my free time, document things related to the Media Device Framework of Amarok, with the double purpose of helping to ease in new device developers, as well as to spark discussion about the framework to make it better. I'm well aware of many of its flaws, but the more eyes the better of course, especially when I have nearly no time to work on it.

One helpful thing the UML has helped to do, in particular sequence diagrams, is to spot where bottlenecks occur (where things can lock up the GUI) and thread them. One such big one with parsing device metadata has become threaded, so some of you with rather large collections on your devices may notice that the GUI no longer locks up during the parse. This applies to iPods, MTP, and UMS devices. So yay.

Hopefully as I do more diagramming, this will make it easier for me to work on Amarok when my brain/body are otherwise quite occupied with other things.

--------

Off-topic: to the KDE person I ran into in downtown Mountain View coffee shop, please leave a comment so that I may remember your name.

Thursday, November 19, 2009

Open Source Coding Hiatus


Where have you been?

So lately I've been occupied by a few things:
  • Family issues
  • Working for a startup company
  • University bureaucracy
  • Jobhunting
Which is not to say I've been without free time. What have I been using my free time for?
  • Studying natural languages more in-depth
  • Reading technical books, and inspiring books
  • Being with friends, having fun and discussing the near and long-term future
So where does this leave open-source coding, for which I've even been given the honor of being listed as author for a great project like Amarok? After all, I have a vested interest in continuing to improve something I spent so much time on. I'll explain a few factors of the times that I've tried to get back into coding for it.

Have you been coding in secret?

The nice thing about using git for development is that I can continue to work on a feature or large fix on the side, and then deploy it when ready. That said, this is the cycle I usually go through when I feel I'm going to have enough time and effort to code on Amarok:

  1. git pull
  2. make install
  3. Check out new stuff
  4. Figure out what I want to fix/add/work on
  5. Start working on it in a git branch
  6. Realize after a few hours, that this is going to take 1-2 weeks of dedicated coding, and stop.
I then may come back in a week or two, delete the old branch because I feel I was going about things the wrong way, and repeat this cycle. This is by no means productive, but is something I end up getting caught in lately.

Clearly this doesn't work, so what now?

So this time around I'm trying something new. I'm fully-documenting the issues I want fixed and how to go about them, and sitting on them a bit to see if I can mature them before coding. Also I'm trying to break them up into doable smaller pieces, so I can at least get checkpoints in progress, otherwise this isn't going to work at all.

And in the immediate future?

I am now entering my last two trimesters of undergraduate studies before graduation. Between work, school and family, I highly doubt I'll have the motivation to work on open source on the side. I'm aware there are others who can do this, and have that motivation, and I look up to and respect them, but I lack that. I hope that this next summer, I'll find myself more motivated and free.

Sunday, November 15, 2009

Go Qt Bindings Worth It?

So there's this language called Go from Google now, whose first impression to a programmer is "this is some odd-looking C" code. I do notice that the compile and link time is blazing fast, but let's take a look at the binary size of a simple hello world program, compared to C and C++ equivalents.

---------------------------------
C:

#include

int main( void )
{
printf("Hello World\n");
return 0;
}

C++:

#include

int main( void )
{
std::cout << "Hello World!" <<>}

Go:

package main

import "fmt"

func main() {
fmt.Printf("Hello World\n")
}
---------------------------------


.... and the output sizes?

628K 6.out
16K helloc
16K hellocpp


Hmmm... speedy compile, strange-looking code, obscenely fat 39.25 times as large binary for a hello world file. Maybe as the programs grow larger, the overhead gets less and less, I'd need to test that or read an article about it, but from my first impression? Yikes... maybe not yet ready for Qt. But I'll definitely have fun playing with it anyway! =D

Monday, November 9, 2009

Yakuake For Clipboard

Yakuake is a great drop-down terminal, but often I find the need to store several things on my clipboard, and was thinking a yakuake-like program that has tabbed sessions of kate/kwrite would be really useful as well.

I'm not sure if there exists an application that already does this, but would anybody be interested in this kind of program?

Wednesday, September 30, 2009

Nokia Browntooth enabled…(Engrish.com Repost)


"Let me call you back, we’ve got a crappy connection…"

I wonder that this isn't what Nokia means by Qt everywhere...

Wednesday, September 2, 2009

Qt for S60 Still Bogged Down By Symbian

Qt for S60 has brought the simplicity and power of Qt to Symbian phones, but there are still a few corner cases which are hurting, and one of those is the camera, whose code is still heavily tied to old Symbian cruft.

Symbian's code for cameras returns captured images as CFbsBitmaps. Don't even begin to guess what CFbs stands for, you'll just end up crying "why, why!?" Luckily Qt for S60 provides a function which converts CFbsBitmaps to QPixmaps, but it seems that the image capture is faulty, even though if at any point you take an image from the viewfinder and convert it it turns out fine.

So I decided to debug to see if the CFbsBitmap returned from the camera's viewfinder on capture was the source of the problems, and not Qt's conversion function.

After an hour or so of Googling (tm) and messing around in the Nokia forums in dead ends, I've found this wonderful snippet of code to save the CFbsBitmap to a file to see if that's the case (http://discussion.forum.nokia.com/forum/showthread.php?p=636992). (Note: CFbsBitmap's Save() function merely saves the binary CFbsBitmap to a file, unopenable by anybody other than Symbian, and thus useless):

------------------------------------------------

_LIT(KFileName, "c:\\1.bmp");
_LIT8(KMime, "image/bmp");
RFs& fs = CEikonEnv::Static()->FsSession();
CImageEncoder* encoder = CImageEncoder::FileNewL(fs, KFileName(), KMime(), CImageEncoder::EOptionAlwaysThread);
TRequestStatus status = KRequestPending;
encoder->Convert(&status, *bitmap);
User::WaitForRequest(status);
delete encoder;
User::LeaveIfError(status.Int());

------------------------------------------------

Let's break this monster down:
· _LIT8 is one of Symbian's ass-backwards ways of declaring a "string" for example a string called KMimeType with value "image/bmp"
· RFs is a file session, which is basically a guy that manages accesses to files, and here we pull out the manager for the application using CEikonEnv (again, don't ask)
· Then we create an encoder to change the CFbsBitmap into a real bitmap and save it to a file with the rest of this wonderful piece of code

The Qt equivalent of this is:

QPixmap *pix:
pix.save( "somewhere.format" );

Why was this so hard to program into Symbian!? If you're going to put a function to save the raw binary of a CFbsBitmap to a file, why not a truly encoded one?

Every day I code in Symbian, I feel a piece of my logical mind get torn to pieces.

Sunday, August 16, 2009

Amarok 2: Universal Mass Storage Device Support Here


Ok, so you can now do the usual with UMS devices that you can with other devices. Due to some issues with Solid detection in Amarok, to make sure your device is found you must:

- create a file ".is_audio_player" at the root of your device
- start Amarok
- the device should show up next to the local collection
- right-click it and click "read device"

Then it should parse, and you're ready to go. You can copy and delete files from outside of Amarok, and Amarok should update accordingly. Copying and deleting from within Amarok, and editing track details also works.

OPTIONAL:
If you want to set a music folder on your device, then put this in your ".is_audio_player" file:

audio_folder=musicfolder

... where "musicfolder" is a relative path from the mountpoint of the device, so this would set the folder to: /media/yourdevicemountpoint/musicfolder

NOTES:
- reading of the device is not done automatically right now since we don't want unpleasant surprises for people with huge external hard drives that happen to be mounted
- yes, the ability to set custom device paths and mountpoints will be coming, but not just yet
- yes, support for multiple music folders on the device is planned
- no, artwork isn't yet supported
- no, saving playlists isn't yet supported

And... bug reports are now welcome, so test away!

Thursday, August 6, 2009

Monday, July 13, 2009

GCDS: Wrap-Up

A few things since last blog post:

  • Met lots of people and didn't get stuck with the same group the entire time
  • Got some work toward Amarok done (not as much, thanks to beer/people)
  • Got to talk to Gnomies, civilized conversations

Obligatory pictures:




Picture of Nikolaj taking a picture of the city with a far better camera than mine.

Metal giraffe meets metal man-thing!  I don't know, this was near one of the parties and I thought it was weird enough to merit a photo.


"Taiwanese" restaurant, ended up going 3 times to mainly because it was cheap.  Ranks 4-6 on the 1-10 scale of delicious/price ratio for Chinese food.  The people working there were mainlanders, not Taiwanese.  Not what I'm used to, but amazing enough to find a Chinese restaurant on an island off the coast of Africa I guess.


Paid breathalyzer test!   You blow into a straw into this machine, and it tells you if you can drive or not.  Yeah...

Anyway, a good conference, read everyone else's long blogposts about things that happened and opinions on things and such.  That's all for this one.

Tuesday, July 7, 2009

ATTN: OWNER OF AN ONITY PASS CARD

I've found an Onity pass card that could be from a hotel or something, it says "Onity innovative thinking" on the front and has operating instructions on the back. If you have lost a card, please let me know.

Sunday, July 5, 2009

Gran Canaria: A Few Photos

Words are boring, keeping it short:
  • Good keynote speakers
  • People misconstruing speech
  • Overpriced food
  • Coffee and Ice Cream
  • Bad internet, no plugs
  • Good discussions with cool people
  • Same warm weather each day (twilight zone)
  • People who speak odd/bad Spanish, and no English
  • Having to translate for everyone due to the above



Vodka for breakfast anyone? For some reason the buffet here thought this was a good idea. I suppose the rich old Europeans might get impatient and need something to calm their nerves while their mountains of high-calorie food arrive.



It seems that a ~ is missing in a most unfortunate place. For those of you who don't know Spanish, this cake says something like "Happy anuses."



1/2 a kilo of ice cream for about 6 euros 50. Downed it between Leinir and me.

More to blog at some point when I have more words. This blogpost was a day in the making. That's how long it took to upload my photos without a timeout. Right then, bye for now!

Monday, May 11, 2009

GSoC: Boston/Cambridge Dev Sprint


The dev sprint was filled with conversation on all sorts of topics, open-source software and pop culture references, but above all, people got set up to go on their GSoC projects and got inspired by each others' enthusiasm.  This being my second time doing GSoC for the same project, I was already set to go and know my way around development, but this gave me a chance to meet with a fellow Amarok developer Jeff Mitchell, and now I've met a good amount of the core Amarok team, which is awesome.  In the end I didn't get a lot of actual coding done, but I took from the sprint enough inspiration to hurry up even more on the code I'm working on.

Highlights:

- MIT == We spent a good amount of time in one of MIT's buildings on our laptops (a photo on Marcus' blog).  Spent time on getting people set up on svn, setting up distributed compiling with IceCream and a bit of hacking.  Above all it set the pace for a lot of conversation which is really what the open source community is about: sharing ideas so that later on, you can work on making them real.

- OpenSuSE's IceCream == Not satisfied with the slow compiles of core stuff like Qt and our own huge projects, we tried to set up IceCream distributed compiler to get more bang for our byte.  Unfortunately we were doomed to failure (found out later) since some of us were 32-bit systems others 64-bit, and differeng GCC versions, and cross-compilers take too long to build.  However, we did get it somewhat going in the hotel, which was nice.

- JP Licks Ice Cream == In a word, amazing.  Suffolk County's own local chain, which redefines what a "small" ice cream should be.  I haven't seen so many unknown or strange flavors in a while, ranging from black raspberry, to peppered ice cream.  You definitely get your money's worth, but I had trouble even finishing the small.

- Indian Restaurant (don't recall the name) == More food than you could hope for, for the right price (the rest of Boston/Cambridge was quite pricy).  Had Chicken Tikka Masala (obligatory), Garlic Naan (also obligatory) and a ton of rice.  I should've gotten more spicy food but I wanted to play it safe.

- Star Trek @ IMAX == Nevermind why Reading has an IMAX theater in a furniture store, the movie was quite a visual spectacle.  The story/characters/acting was exactly what I expected, and I wasn't let down.  I'm sure Star Trek fans enjoyed it more since there seemed to be a lot of hidden humor, but luckily the few bits I've seen helped me out.

- Candlepin Bowling

== Unlike the 10-pin bowling I'm used to, here you get a ball the size of a skiball, pins aren't cleared until 3 shots, and the pins are cylinder-shaped.  Definitely interesting.

- The Kendall Hotel == Nice hotel, right in front of MIT, right next to the T.  Wireless was hassle-free, breakfast every morning.  Overpriced food can't be helped, but I went it cheap.  Nice beds and nice rooms, all that was needed for some late-night hacking.

- The T == The big pitfall of living in California is that the concept of mass public transportation is, to put it politely, lacking.  The Boston T, for about $2, will let you ride from one side of Boston to the other, and even to Cambridge and other outlying areas.  Reasonably fast, reliable, and not too packed.  Definitely one thing I would love to have here in car-driven California.

- Dunkin Donuts == There are ~300 of these in Boston alone, which is mind-boggling.  There's a DD underground in the T, there's one at Logan Airport, there's one in the MIT admin building!  Such cheap, decently-flavored iced cofee you will not find elsewhere, and the monstrous size of the large was worth the price.  Definitely went again and again...

- Dunkin Donuts == .... and again

- Dunkin Donuts == .... and again.  I got a lot of coffee in Boston.  I don't think I've ever had so much consecutive coffee drinking in my life.  Definitely missed on the west coast.

The People:

Veteran Devs:

Jeff Mitchell -- The guy who worked hard to make this all happen, and go well, and a fellow Amarok dev.  Many many thanks for making this possible, and for not getting too frustrated with my lack of brainpower in navigating directions and so forth this last weekend.

Marcus Hanwell -- Avogadro dev, soon to be working on our beloved build-system CMake.  Really cool guy, loves photography, well-travelled.

GSoC Students:

Chani Armitage -- Plasma dev, brought you screensaver plasmoids, now working on fancy popups using mouse buttons.  Energetic and very involved.

Constantin Berzan -- Working on a global outbox for Akonadi, to take away dependence on e-mail related things from KMail to free e.g. applets to do stuff with mail.  Good at directions, shame he had to go back so soon in the sprint.

Christopher Ing -- Bringing fluids to STEP.  Good roommate, made sure I didn't miss breakfast the 2nd day =)  The only mac user in the group, which shows the variety of people working on KDE-related things.

Ramon ZarazĂșa -- Working on refactoring support for KDevelop 4.  I really look forward to the results of this project, being an avid KDev 4 user.  Cool guy, the only one with whom icecream was working.

Adam Kidder -- Nepomuk search.  Picked up the slack for my lack of common sense this last weekend ("you need an IP address to run a dhcp server?").  At Ann Arbour, my cousin went there.

Marwan Hilmi -- Parsek.  Didn't get much of a chance to talk to him about his project, but seemed cool.  Note to self: round tables are only good if people aren't too far away from each other.

Pierre-Alexandre St-Jean -- Abstracting Kopete chat window for use in other apps.  Probably the only relaxed person of the bunch (most of the rest of us were doped up on caffeine).  

Conclusion:

Completely worth the 3,000 mile trip.  It looks like this GSoC, for KDE at least, will be filled with a lot of awesome people and work getting done.  These kinds of get-togethers help to motivate us to do awesome things, and to open up channels of communication between different parts of KDE which is essential to making KDE cohesive as well as feature-filled.  I don't think I'll be making it to Akademy this year unfortunately, so I'm happy I was able to make it to this.

I would, at some point, like to set up a similar event in California, perhaps in San Francisco or San Diego, and I wonder who would be interested in it.  

At any rate, good luck to all GSoC'ers on your projects, and I'll see you on IRC/ML.

Sunday, May 3, 2009

Amarok: Quick Status Report on Refactoring, Git Rocks

Between the business of school &c. I've been at work making Media Device code smaller and easier to write, as promised. Here is a preview of the difference in the amount of code required before, and in my git branch after. Let's just look at the MediaDeviceCollectionFactory subclass for Ipods, which keeps track of Ipods connected and talks to Solid.

Before:


AMAROK_EXPORT_PLUGIN( IpodCollectionFactory )

IpodCollectionFactory::IpodCollectionFactory()
: Amarok::CollectionFactory()
{
//nothing to do
}

IpodCollectionFactory::~IpodCollectionFactory()
{
DEBUG_BLOCK
}

void
IpodCollectionFactory::init()
{
DEBUG_BLOCK

// connect to the monitor

// connect( this, SIGNAL( ipodDetected( const MediaDeviceInfo & ) ),
// MediaDeviceMonitor::instance(), SIGNAL( deviceDetected( const MediaDeviceInfo & ) ) );

connect( MediaDeviceMonitor::instance(), SIGNAL( ipodReadyToConnect( const QString &, const QString & ) ),
SLOT( ipodDetected( const QString &, const QString & ) ) );

// HACK: emitting old signal to avoid refactoring applet yet
connect( this, SIGNAL( tellIpodDetected( const QString &, const QString & ) ),
MediaDeviceMonitor::instance(), SIGNAL( ipodDetected( const QString &, const QString & ) ) );

connect( MediaDeviceMonitor::instance(), SIGNAL( ipodReadyToDisconnect( const QString & ) ),
SLOT( deviceRemoved( const QString & ) ) );

connect( MediaDeviceMonitor::instance(), SIGNAL( deviceRemoved( const QString & ) ), SLOT( deviceRemoved( const QString & ) ) );

// HACK: Usability: Force auto-connection of device upon detection
checkDevicesForIpod();
}

void
IpodCollectionFactory::ipodDetected( const QString &mountPoint, const QString &udi )
{
DEBUG_BLOCK
IpodCollection* coll = 0;
if( !m_collectionMap.contains( udi ) )
{
debug() << "New Ipod not seen before";
coll = new IpodCollection( mountPoint, udi );
if( coll )
{
// TODO: connect to MediaDeviceMonitor signals
connect( coll, SIGNAL( collectionDisconnected( const QString &) ),
this, SLOT( slotCollectionDisconnected( const QString & ) ) );
m_collectionMap.insert( udi, coll );
emit newCollection( coll );
debug() << "emitting new ipod collection";
}
}
}

void
IpodCollectionFactory::deviceRemoved( const QString &udi )
{
DEBUG_BLOCK
if( m_collectionMap.contains( udi ) )
{
IpodCollection* coll = m_collectionMap[ udi ];
if( coll )
{
m_collectionMap.remove( udi ); // remove from map
coll->deviceRemoved(); //collection will be deleted by collectionmanager
}
else
warning() << "collection already null";
}
else
warning() << "removing non-existent device";

return;
}

void
IpodCollectionFactory::slotCollectionDisconnected( const QString & udi)
{
m_collectionMap.remove( udi ); // remove from map
}

void
IpodCollectionFactory::slotCollectionReady()
{
DEBUG_BLOCK
IpodCollection *collection = dynamic_cast( sender() );
if( collection )
{
debug() << "emitting ipod collection newcollection";
emit newCollection( collection );
}
}

void
IpodCollectionFactory::checkDevicesForIpod()
{
QStringList udiList = MediaDeviceMonitor::instance()->getDevices();

/* poll udi list for supported devices */
foreach( const QString &udi, udiList )
{
/* if ipod device found, emit signal */
if( isIpod( udi ) )
{
// HACK: Usability: Force auto-connection of device upon detection
QString mountpoint = MediaDeviceCache::instance()->volumeMountPoint(udi);
ipodDetected( mountpoint, udi );

//MediaDeviceInfo *deviceinfo =
new IpodDeviceInfo( mountpoint, udi );
//emit ipodDetected( deviceinfo );
// HACK: emit old signal to avoid refactor of applet yet
emit tellIpodDetected( mountpoint, udi );
}
}
}

bool
IpodCollectionFactory::isIpod( const QString &udi ) const
{
DEBUG_BLOCK

Solid::Device device;

device = Solid::Device(udi);
/* going until we reach a vendor, e.g. Apple */
while ( device.isValid() && device.vendor().isEmpty() )
{
device = Solid::Device( device.parentUdi() );
}

debug() << "Device udi: " << udi;
debug() << "Device name: " <<>deviceName(udi);
debug() << "Mount point: " <<>volumeMountPoint(udi);
if ( device.isValid() )
{
debug() << "vendor: " << device.vendor() << ", product: " << device.product();
}

/* if iPod found, return true */
return device.product() == "iPod";
}

After:

AMAROK_EXPORT_PLUGIN( IpodCollectionFactory )

IpodCollectionFactory::IpodCollectionFactory()
: MediaDeviceCollectionFactory ( new IpodConnectionAssistant() )
{
//nothing to do
}

IpodCollectionFactory::~IpodCollectionFactory()
{
DEBUG_BLOCK
}

----------------------------------------------------------------------------------------------

As you can see (excuse the bad formatting, blogger doesn't take kindly to source code), the amount of code required has been greatly reduced, and the other required classes are soon to follow. Also, things are going to be implemented more in the predictably correct classes now, and after refactoring is done and I've ported both Ipods and MTPs to it, I will write a small tutorial on how to go about implementing your own device. No, UMS will be done by me, heh, but it should be a piece of cake afterward to implement support for some of the other devices some of you miss from Amarok 1.4, so yay!

Unfortunately I'm fairly busy with school too so this proceeds in big bumps every 4-7 days, might take a bit, but getting there. I'm going to Boston next weekend for the KDE GSoC meetup, which should be fun. If you're around, do say hello!

Saturday, April 25, 2009

Amarok: A Better Media Device Experience, GSoC 2009

So I have again the pleasure of being selected for Google's Summer of Code for Amarok to scratch some very serious itches concerning media device support in Amarok 2.

Itches:

  • Playlist Support
  • More GUI Feedback, more intuitive interface
  • UMS(Universal Mass Storage) Support

Playlist:

Actually, iPods in Amarok already have their playlists read on connect, but at the time I wrote the code, the code in Amarok for any collection dealing with playlists wasn't at a satisfactory level yet, which I believe it to be now thanks to the work of a few people, in particular I know that Stecchino (Bart) has worked on it.

GUI:

The media devices applet seemed like a good idea at first, but it's terrible from a usability standpoint, and since the PUD (Popup Dropper) removes any possibility of dragging-and-dropping tracks onto it, for instance, it doesn't make much sense to have it.  However, I understand there's plans in the works to redo some of Amarok's GUI, part of which will accomodate the previous functions of this applet, and I'll be taking advantage of that.

UMS Support:

Yes!  I swear it this time.  It turned out that building a new collection-based media devices infrastructure more-or-less from scratch took a lot longer than planned last summer, and I did not get to UMS.  Another reason I've held back on it up until now is that media device support in general is going to get a massive refactoring before GSoC begins, to accomodate for simple adding of support not only of UMS devices, but in the future, other types as well.

Ok, now that the explanations of GSoC are out of the way, I move on to something else.

People with media devices, aside from the above, what is it you would like to see in Amarok for devices?  I can list a few off the top of my head, please list more so that I can prioritize perhaps some time for this summer and beyond.

  • MTP Cover Support
  • iPod stale/orphaned scan support
  • Playlist synching with the local collection

Saturday, February 14, 2009

OpenSolaris, Qt and Game Development

Overview

A group of 3 other people and myself were charged with making a game for a class this trimester, which is essentially a Final Fantasy clone with a few quirks localized to our university. In thinking of a toolkit, I thought to myself "what event-driven toolkit provides a graphics system and paint system complete and robust enough to make this happen?" Naturally Qt came to mind. The professor suggested some Java toolkits, including SWT, but my experiences with SWT have not been at all good, so I decided to give Qt a shot. Another perk of Qt over SWT is how easy it is to learn and use, since my 3 team members are not familiar with it.

After a few days of playing with Qt tutorials on the Graphics framework and studying KDE games code, I had a small but working prototype of one of the modes of our game, where the character explores the scene of a level.




Things to notice that were easy to do:

- Creating a graphics item from a graphic file
- Moving it around
- Having it change form
- Collision detection with walls
- Dragging of the view to see different parts of the scene

Deployment

Before proceeding I had to make sure that the program would run on the target platform of the school servers: SunOS 5.10 (Solaris). Now Qt is a cross-platform toolkit, and binary builds of it are provided for Linux, OS X, and Windows, but not for Solaris (that I could find here).

Having recently installed VirtualBox after hearing lots of good things about it, I decided to give Solaris a spin as a virtual machine. There was a bit of confusion for me at the beginning with so many possible distros to choose from, but luckily since only 2 of them are supported by the KDE Solaris team, that narrowed it down. They prefer using SXCE, so I gave that a shot, but unfortunately some bug where X would show up but then freeze on the live dvd stopped me short (I figured it was an issue of running in a VM or something). Then I tried OpenSolaris 2008.11, which installed fine

Then the problem became that the instructions on the wiki for compiling using OpenSolaris were a bit lacking, a problem I have since mended with some updates based on my experience. After much strife with getting the environment set up just right, compiling was not a big deal, thanks to the awesome efforts of the KDE OpenSolaris team. I ran into some issue with a Qt example not compiling, and hacked it up to fix it, since it didn't much matter, and voila, Qt was on the system, and my previous example in the youtube video worked.

From here, I had a few options (as I saw it):
- build Qt as static, deploy a static binary
- build Qt as shared library, ask school admins to install Qt on servers
- build QtJambi, port to Java, deploy as jar

Since building Qt as static was not supported by the KDE Solaris team, I decided to give QtJambi a shot, and ported my example to Java. Unfortunately the QtJambi build specfile provided didn't work too well, and went into an infinite recursive make loop.

When at last I had almost given up, I discovered that the shared library approach doesn't actually require the system to have Qt installed on it, just that the necessary .so shared object files be deployed with the program itself, and to use a script to launch the program (a script which simply adds current directory to linker path).

A simple ldd resulted in this:


libc.so.1 => /usr/lib/libc.so.1
libQtGui.so.4 => /opt/foss/qt4/lib/libQtGui.so.4
libQtCore.so.4 => /opt/foss/qt4/lib/libQtCore.so.4
libCrun.so.1 => /usr/lib/libCrun.so.1
libm.so.2 => /usr/lib/libm.so.2
libglib-2.0.so.0 => /usr/lib/libglib-2.0.so.0
libpng12.so.0 => /usr/lib/libpng12.so.0
libSM.so.6 => /usr/lib/libSM.so.6
libICE.so.6 => /usr/lib/libICE.so.6
libz.so.1 => /usr/lib/libz.so.1
libXrender.so.1 => /usr/lib/libXrender.so.1
libXrandr.so.2 => /usr/lib/libXrandr.so.2
libXfixes.so.1 => /usr/lib/libXfixes.so.1
libXcursor.so.1 => /usr/lib/libXcursor.so.1
libXinerama.so.1 => /usr/lib/libXinerama.so.1
libfreetype.so.6 => /usr/lib/libfreetype.so.6
libfontconfig.so.1 => /usr/lib/libfontconfig.so.1
libXext.so.0 => /usr/lib/libXext.so.0
libX11.so.4 => /usr/lib/libX11.so.4
libgthread-2.0.so.0 => /usr/lib/libgthread-2.0.so.0
libnsl.so.1 => /lib/libnsl.so.1
libsocket.so.1 => /lib/libsocket.so.1
libexpat.so.1 => /usr/lib/libexpat.so.1
libXau.so.6 => /usr/X11/lib/libXau.so.6
libpthread.so.1 => /lib/libpthread.so.1
libmp.so.2 => /lib/libmp.so.2
libmd.so.1 => /lib/libmd.so.1
libscf.so.1 => /lib/libscf.so.1
libuutil.so.1 => /lib/libuutil.so.1
libgen.so.1 => /lib/libgen.so.1
libXevie.so.1 => /usr/X11/lib/libXevie.so.1
libXss.so.1 => /usr/X11/lib/libXss.so.1



Wow, that's a lot of shared objects! According to the Qt deployment guide though, all of the X libraries could and should be avoided to be packaged. I did end up adding other ones though, one by one, as I saw necessary until the program finally ran without a linker error. The bad news is this blew the total package up to 30 MB or so. Oh well, so be it, it ran!

And now...?

And now the real development can begin. There's only a few weeks to work on it, but that should be plenty. It won't be a terribly fantastic game as a result, but it was an interesting adventure, and more importantly proves the point that Qt is an awesome toolkit, and that there are quite a few options open for deployment.

Thanks to the KDE Solaris team for helping me with getting things building, I'd be nowhere without your help (in particular: szt, [ade], steleman, and trochej thanks a lot guys).

Tuesday, February 10, 2009

Karaoke with Windows (via VirtualBox)


Some time ago, a friend gave me this Chinese karaoke program called HomeKara2, which puts out a song-selection screen to one monitor, and the actual video with lyrics to another. I thought this was nifty, and tried to virtualize it with wine. First, to get Chinese working, I tried this "wineloc" project I used for my Japanese programs. No go. Also, the dual monitor output thing wasn't working. Bummer.

Recently I got hooked up with VirtualBox, a handy replacement for vmware for me, which I've been using for an OpenSolaris machine for developing a Qt game (that's a blog post to come). Somewhere along the line, I set up a Windows XP VM, just to test, and was surprised that it ran quite well, so I decided to put it to the test with HomeKara2.

I ran into some obstacles again, starting with that HomeKara2 has not a UTF-8 codepage, but some Chinese one. I decided to try the good 'ol Microsoft applocale program that changes codepages. This worked amazingly! Until the program crashed randomly and inexplicably at different times. Another problem was that the program uses an external MDB (Microsoft Access Database) file to keep track of the tables of artists, songs, etc, which is not readily editable or even viewable on Linux without extra tools. Last but not least, I had to figure out how to get multiple monitors set up within the virtual machine.

My solutions are out of order of how they happened, but in the order as previously mentioned

The applocale program is apparently quite unstable, and all I had to do to get HomeKara2 to run correctly without it, was to set the default codepage for non-utf8 codepage applications in Control Panel's regional language settings somewhere. This required a quick vm reboot, which was fine.

For the MDB issue, I sought out some freeware editors, which are in general wonderful, but realized that the Windows version of OpenOffice can connect to an MDB file and modify existing tables. A bit fat of a solution to install OpenOffice, but I can't doubt the ease of it.

The multiple monitors issue was a bit tough, but some googling around eventually brought up the right combination of answers. First, shut down the VM if it's running, and start up a terminal.

Note: replace VMNAME with the name for your VM

1. Use the VirtualBox GUI to enable VRDP (remote desktop) and change the port, in case Windows doesn't like you using its default RDP port, and take note of the port.

2. `VBoxManage modifyvm VMNAME -monitorcount 2` will set the number of monitors on the machine to 2.

3. `VBoxManage modifyvm VMNAME -vrdpmulticon on` will allow for multiple connections to the same RDP port. This allows you to connect twice, once for each monitor.

4. Start up your VM as normal, right-click the background wallpaper, click properties, goto settings tab, and select decent sizes for each of your monitors, checking the box for "extend my Windows desktop into this monitor" and apply.

5. Shut down your VM.

6. `VBoxHeadless -s VMNAME` will start your VM in a headless mode (like a daemon) which will listen on the port you specified for RDP connections.

7. Use an RDP program (I use KRDC on KDE), and set up an RDP connection to 'localhost' at your port, i.e. 'localhost:port'. When KRDC asks for extra options, put in '-d @1' and this will connect you to monitor 1 of the VM. Adjust resolution as necessary.

8. Repeat step 7, but change '-d @1' to '-d @2' to connect to the second monitor.

9. KRDC allows you to full-screen each desktop. In my setup, I use nvidia-settings to set up twinview, then put a KRDC instance on each desktop, and fullscreen.

10. Run HomeKara2, and behold the beauty of success.

Notes: be careful with sound forwarding on KRDC, as it might cause an echo. You can just choose to keep sound on "remote only" to fix this.

-- Interesting little other hack --

My friend gave me his music videos by putting them on my iPod, along with the program. I don't have much room left on my laptop's hard drive, so I did something somewhat hackish which actually worked.

1. I mounted the iPod with this long command:

`mount -t vfat -o rw,nosuid,nodev,uhelper=hal,shortname=mixed,uid=1000,utf8 /dev/sdb1 /media/ALEX_IPOD`

The real trick here was the shortname=mixed, which makes sure capitalization is done correctly, and the _long_ vfat names are used. Weird stuff can happen with the default mode on Kubuntu's mounter.

Beforehand, I had set /media/ALEX_IPOD as a shared folder for VirtualBox, so to keep consistency I mounted there again. I then changed the cdrom's drive letter to not D: and assigned D: to a particular folder on the iPod, so that the path lined up perfectly with the path listed in the MDB file for the videos. This worked quite well, so I was able to get away with not modifying the MDB file's path for videos, and with reading all videos directly off the iPod.

-- end hack --

So what did this all look like in the end?



Well OK, later on I fixed the resolutions so that each Windows "monitor" would take up my entire monitor, for both monitors, but this is my setup with my laptop screen and a classic CRT. Not bad for a day's work I'd say, and now I can set up haphazard karaoke when hanging out with friends and there's no place nearby. Nice!