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!