Monthly Archives: July 2012

GSoC Progress Report #4 – MidTerm passed

This is the 4th post in the series of my biweekly gsoc status reports. Last week was MidTerm deadline, and I am happy to say that I passed my MidTerm evaluation. I am a little ahead of time, actually. I proposed to have a Banshee.app ready with no working Mass Storage yet, but preview USB plug-in detection. The last alpha3 build already had full usb mass storage support working. So I had the time in the last two weeks to polish the hardware support a little.

Sync your music to network shares with Banshee

I’ve modified the OS X specifc hardware detection code a little, so that not only USB devices get recognized, but all kind of mountable volumes that have an .is_audio_player file on them. This allows one to create a fake mass storage device to sync your media to, but it’s actually just a folder on a network share. This can be any kind of network share, like smb or afp mounts, or as I am going to show step-by-step, a remote SSH location mounted by sshfs/MacFusion.

Howto: Syncing to a remote machine over SSH

I want to be able to sync my media collection and selected playlists from Banshee to my linux powered File-/DLNA-/ Server where I store all my music. I’ll only want to carry a subset of tracks on my Macbook, which has only limited disk space. This is how we can enable syncing via SSH (provided you use at least alpha4 build):

  1. Login via ssh to the machine to want to sync to, and create a folder for your Music and put an .is_audio_player into it:
    mkdir ~/SharedMedia/
    mkdir ~/SharedMedia/Music
    mkdir ~/SharedMedia/Playlists
    touch ~/SharedMedia/.is_audio_player
  2. Edit the .is_audio_player file with your favorite editor and have it look like this:
    audio_folders=Music/
    folder_depth=2
    output_formats=audio/ogg,audio/x-ms-wma,audio/mpeg,audio/wav,audio/x-flac
    playlist_path=Playlists/
  3. On your OS X system, install MacFusion (successor of MacFuse)
  4. From the MacFusion tray icon, select “Connect to Server” and enter the ssh:// address of your remote machine. In my case, this is “ssh://timo@orion/home/timo/SharedMedia/”. Replace “timo” with your username and “orion” with your  hostname of your machine. You will need to have setup ssh public key authentication for the connection to succeed!
  5. Banshee will detect the network share as a generic mass storage device. You can now sync your whole media collection or single playlists between the network share and your banshee media database! 🙂

Other improvements in the hardware backend include stability fixes as well as making the “Eject” button working for the external devices.

Native file dialogs

Also new in alpha4 is the support for native file dialogs. Right now, the Gtk file open dialog is just broken on OS X. If you own a system with more than one harddrive (no matter if internal or external through usb/firewire/thunderbolt) the Gtk Filechooser will not display it. Same holds true for any network shares. Only way to access external storage is, if you know that OS X mounts those volumes in your /Volumes path – a fact that is not known to lots of OS X users (and there is no need to, as you got your external Volumes always in your sidebar). Currently only the Import Media->From File/Folder uses the OS X native file open dialog. At other points, its more complicated due to Gtk Widgets being embedded in the chooser. But those dialogs are usually less often used (export playlist dialog, choose cover art dialog).

As usual, with this bi-weekly report I’ve rolled a new alpha bundle which included my latest development progress and all features talked about in this post, as well as all previous posts. Get it here or follow this direct download link to test it yourself!

Source Code

Since the source for the hardware support and the native file choosers will likely change within the GSoC period, I’ve not submitted patches to upstream, yet. However, I’ve setup a mirror on GitHub including latest banshee master branch from gnome, and a branch with my changes (nicely formatted and rebased). A pull request against myself can be used to retrieve a single patch including all my changes for this GSoC assignment. I’ve also updated the banshee-git package in bockbuild to auto-retrieve this patch and build when doing a release build.

GSoc progress report #3

This is my 3rd post in the series of my bi-weekly status reports for my GSoC banshee OS X assignment. This two weeks period was actually quite more fun than the weeks before, as I shifted from doing packaging and bugfixing work (which is sometimes very time consuming and frustrating when dealing autotools and  recompiling packages over and over again to check for regressions) to actual coding work.

Hardware support

Part of my self-set midterm goal is bringing basic support for hardware devices in OSX banshee, in particular to USB mass storage devices. Mass storage devices are very common: From the first generation of mp3 players, the mass storage usb  driver was used to put mp3 files into the players flash memory and it is still widely used today: All recent Android phones support it, as well as low-cost consumer mp3 player sticks and more sophisticated “feature phones” are also often loadable via usb mass storage. That makes having mass storage support in OS X banshee very important.

OS X disk arbitration library

After little research, I found there are several methods to access usb devices on OS X. There is the IOKit framework, that can be used to handle everything usb related, as far as low level device driver programming. Luckily, there is another Framework that is a little higher on the device layer while not being bound too strictly to USB and fits perfectly for our purposes: the DiskArbitration framework. You can use it to hook callbacks whenever a disk device (being a USB/Firewire mountable volume like a usb stick or harddrive, network shares or .dmg images) appears or disappears to the system. So I chose to go for it and started research.

Unfortunately, neither the IOKit nor the DiskArbitration framework are yet bound in MonoMac. That meant I had a number of choices:

  • writing myself a C based glue layer to interface with the frameworks
  • bind the needed function calls myself with DllImport P/Invokes and wrap the datatypes

The first way is usually an easier one from a programmers perspective, as I could do everything in C and just write a very basic public interface that is marshaled by the mono runtime. Future changes in the framework’s public ABI can be spotted very easily, as the C compiler will complain about missing functions or changes datatypes.

However, I chose the second way as usually prefer keeping one language in a project. Banshee uses quite some C gluelayers at the moment, bug there are efforts to remove them and someday have a completely C# based codebase.

Although MonoMac did not bind the IOKit/DiskArbitration framework, there is limited support for the CoreFoundation framework which helped doing a managed-only solution. I did never work on low-level OS X APIs before, neither did I work with MonoMac, so I spent nearly a full-time week digging into the Header files (which turned out to be the best documentation for the API) and finding out about MonoMac, and how I could handle the native CFObject types and marhsal them into C#.

If I had more knowledge about MonoMac and OS X internals, I’d have tried to contribute them to MonoMac by binding the missing frameworks. I am however glad I didn’t chose that in the first place, as it turned out I only needed a handful of funtions wrapped, and especially IOKit is a huge beast with far more complexity needed for my purposes. So right now, there are two small static IOKit and DiskArbitation classes that expose the needed library calls via the public static extern DllImport mechanism.

Hooking into disk arbitration wasn’t the difficult part. Turned out, for device recognition I needed the usb vendorId/productId pairs, and those were not provided by disk arbtitration (as its not bound to the USB bus). It took me days to figure out how to do that, and I had a chance to catch up with my rusty C abilities, as I did the prototype completely in C, and then rebuild it in C#.

Outcome

I managed to get USB device recognition working quite well (as far as I could test). In the latest alpha build (see below), you can plugin usb mass storage devices at will, before or during banshee runs, and we hook into all necessary events (device unmounting, hard usb removal because life is to short to remove usb safely) and banshee will refresh the devices list.

The usb vendor/product ID pairs are exposed, so lots of device abilities are detected automatically. My Samsung Galaxy S (with CM9) is correctly detected as an android device, and I tested a simple USB stick with an .is_audio_player file to pretend it being a MP3 player. There might be glitches with devices having more than one partition on them, I have yet to test that.

Syncing works (again as far as I could test) although I had to apply two non-hardware backend related patches (1,2) to make the process work seamlessly.

As I only have a limited number of devices, I invite everyone to test with your devices, and give me feedback so I can further improve the mass storage support.

Minor improvements

The alpha3 build I put together includes, besides the very large hardware-support patch (that is not yet in upstream as it will likely change in the next weeks), enabled  UPnP/DLNA client support . There was not much to do, just create a bockbuild package dependency and it worked out of the box, same way as it does on Linux.

As the folks from xamarin pointed out to me in IRC, there are known problems with Glib 2.32 on OS X which severely impact performance. The (quite old) gcc Apple ships seems to have problem with gcc interlocked/atomic intrinsic (compare-and-swap and alike). I downgraded to Glib 2.30 by reusing the xamarin package and to my great surprise I could actually feel it. The UI is a little more responsive, but the great change is the playback: While I often had sound stuttering when the system was under load, that is completely gone now. That change is also included in the latest alpha build.

New alpha build release

As I had done with the two progress reports before, I’ve bundled a new Banshee.app (this time alpha3) ready for everyone to download and test. Get it from here and do not forget to read the instructions provided. Feedback is greatly welcome, you could use the banshee mailing list for that.