iPod Work

I started working on a generic iPod device class that provides lots of information about the iPod and will work with Snorp’s ipod-sharp. It provides things like the name of the iPod (not the volume name, but the assigned name), the model/type (shuffle, regular, mini, photo), version info, serial numbers, capacity, used space, etc. It also supports safe ejection of the iPod. Initially I was doing this by just calling ‘eject’ on the device.

However, I decided I’d try doing this by making an ioctl call on the device. Not giving much thought to it, I came up with a few lines of code to eject a CD-ROM drive. It didn’t dawn on me until after the CD ejection code was working that the iPod is not a CD-ROM drive (it’s okay, you can smack me). It needs to be ejected as a SCSI device. The ioctl call[s] for this task are much more complicated (a structure must be passed to the device instead of a plain integer), and I’m not sure how to do this easily in C#. I’m not sure that it’s even worth it, and will probably go back to just execing ‘eject.’

Anyway, if anyone wants to eject a CD-ROM drive in C#, here you go. This may be useful for making basic ioctls in C# for other reasons. I’ve never seen an example of ioctl from C#, so maybe this is new.

<br /> using System;<br /> using System.Runtime.InteropServices;<br /> using Mono.Unix;</p> <p>public class SimpleEject<br /> {<br /> public static void Main(string [] args)<br /> {<br /> if(args.Length &lt;= 0) {<br /> Console.WriteLine(&#8220;Usage: mono-eject.exe [-t] <device>&#8220;);<br /> return;<br /> }</p> <p> string device = args[0];<br /> bool open = true;</p> <p> if(args.Length > 1 &#038;&#038; args[0].Equals(&#8220;-t&#8221;)) {<br /> device = args[1];<br /> open = false;<br /> }</p> <p> Console.WriteLine(Eject(device, open)<br /> ? String.Format(&#8220;Device {0} {1} successfully&#8221;, device,<br /> open ? &#8220;opened&#8221; : &#8220;closed&#8221;)<br /> : &#8220;Error ejecting device &#8221; + device);<br /> }</p> <p> [DllImport(&#8220;libc&#8221;)]<br /> static extern int ioctl(int device, EjectOperation request); </p> <p> private enum EjectOperation {<br /> Open = 0x5309,<br /> Close = 0x5319<br /> }</p> <p> public static bool Eject(string devicePath, bool open)<br /> {<br /> try {<br /> using(UnixStream stream = UnixFile.Open(devicePath,<br /> OpenFlags.O_RDONLY | OpenFlags.O_NONBLOCK)) {<br /> return ioctl(stream.Handle, open<br /> ? EjectOperation.Open<br /> : EjectOperation.Close) == 0;<br /> }<br /> } catch {<br /> return false;<br /> }<br /> }<br /> }<br /> </device>

And with that we have a simple Mono eject replacement for basic opening/closing CD-ROM trays. Woo-hoo!

Smooth Music and the LTM

It’s been a while since the last entry, but at least I’ve been up to some good. There have been some exciting happenings regarding Sonance, too numerous and exciting to post here, right now. However, lately I’ve been enjoying iTunes while developing Sonance. I now have an iPod, and am loving it – but it’s not just for play. Currently I am performing five concurrent tasks in iTunes, and am happy to say that Sonance’s backend is ready to handle the same tasks soon. All at once I am Ripping a CD, Importing music to the iPod, Downloading purchased music, Burning a CD, and listening to music. This task load started as me re-ripping most of my CD collection to AAC (vs OGG) in order to actually have content to fill the iPod. In many ways this is a shame – I’ve been using OGG for years, and the only reason to drop it is because the iPod doesn’t support it, and that really needs to change.

Anyway, Sonance handles all of its extensive IO tasks with no lag in the interface at all, like iTunes. This is due to the Library Transaction Manager (LTM). IO tasks are handled through Library Transactions, all which extend a base class, so the LTM can manage the actual transactions. Transactions of the same type cannot be executed concurrently, and are therefore executed in a queue (For instance, you couldn’t burn two CDs at once). However, transactions that are not of the same type can be executed concurrently (I can import, burn, rip, and listen all at once). Additionally, the LTM provides access to the top-most transaction (usually the last transaction initiated), and then an array of the top-most transactions of each type. The interface can then query each transaction for status information. This allows the UI to provide status pages like iTunes – the top-most transaction’s status is displayed first, with the option of cycling to other transactions.

Development for Sonance over the next three months is going to be extremely exciting. A few major target features are iPod support, CD Burning, and CD Ripping. More details on this are soon to follow, when I can find a spare moment.

In somewhat other news, I’ve implemented a nice test case for all sorts of common Drag-n-Drop functionality desired for GtkTreeViews, including multi-row DnD, drag reordering, drop between rows, and drop on a row (both vs. the default drop between or on). This functionality will be included in Sonance, but I wanted to iron out a test case for other projects and make sure the code might not suffer from unrelated factors. I’ll make this available when it’s a little more polished off, and I have another spare moment.

Modern Music Management Experience: In Linux

With Sonance gaining much attention, and development gaining steady ground (though sometimes slow, due to trumping obligations that pay my bills), it is starting to unfold into a more modern environment for managing and playing music.

I am overjoyed with how well Jon Lech Johansen’s SharpMusique works. I purchased my first song through it today. Beautiful. There are plans to integrate it into Sonance for the ultimate music experience yet to be seen under Linux. I can’t wait until I can search for new music in iTms, purchase it, and have it appear shortly thereafter in my Sonance library. Yes, it is sick.

I made an SVN commit today that shows off some of the new functionality/widgets in Sonance, but I’m sure I’ve broken somethings, specifically adding tracks to a playlist. The next SVN commit will be more pleasing and feature complete. After a few more SVN commits, the next public release will be available.

One snag though, regarding which I am rather upset. It appears that you can’t drag-n-drop multiple selected rows in a Gtk.TreeView. This is upsetting because to add new songs to a playlist from the library, I wanted to be able to select them, and drag them onto a playlist in the sources TreeView. Apparently the problem is in GTK, not gtk-sharp. I read there is a hack for the problem in egg, so I’ll investigate that, and see what I can do. It’ll need to be wrapped, which is annoying. It seems like this should be supported in GTK itself. If I am misinformed, or if anyone has suggestions, I’d be glad to hear them!

Sonance Is Going Places

I’ve been actively working on Sonance for the past two weeks, and I have some major developments to report. The new interface is really working out, and since implementing it, I have been able to more easily implement some of the cool features that I have been planning for the last few months. I’m not promising a release date, since there is so much still to do, but at least development is moving smoothly, quickly, and it’s starting to show.

Today the Smart Playlist/Search interface (“Query Builder”) completely fell into place, and generated SQL to be used for smart playlists and searching.

The Query Builder (screenshot) generated this SQL today:

SELECT * FROM Tracks WHERE Artist LIKE '%Matthews%' AND (DateAdded >= '2005-04-11' AND DateAdded <= '2005-04-11') ORDER BY RAND() LIMIT 15

Also, the Library is now loaded automatically in the background when Sonance starts, which takes about 3 seconds for ~4500 songs. Loading the Library into the active view/playlist after that takes under a second. Sonance now has reorderable/toggleable/resizable column headers too, and their state is saved/restored.

The Query Builder uses a custom GTK Date Button widget I wrote, and the whole thing is composed of a few custom widget classes, and a few model classes. Ultimately, the Query Builder widgets/model can be used in other projects with the need of having a semi-complex interface to generating any type of query for searching. It doesn’t have to be SQL. I will publish the Query Builder separate from Sonance at some point for reuse in other projects. If anyone is interested in looking at it now, just contact me.

Finally, I’d like to thank Christian Hergert for letting me on Monologue! I’ve loved reading it over the past few months, and now I look forward to posting on it.

Change of Sonance Plans

After a few posts about Remix (now named Sonance), and getting ready for the first public release, I had a sudden life changing experience as a developer. I discoverd development under Mono. After quickly learning C# and exploring the .NET libraries and the GNOME/GTK bindings for Mono, I wrote a few test programs, and started rewiriting/porting Sonance to C#. Amazingly, the power of the language and bindings are allowing me to more efficiently develop Sonance, and in much less time. In just one week, I have re-developed Sonance with less code, to the same point that the C version was developed in about a month.

The major struggle was the lack of good documentation on the GStreamer bindings for C#, gst-sharp. I have been able to find about three gst-sharp applications. And honestly, and with no disrespect to their developers, their implementations are not very solid, nor featurefull. So in addition to porting Sonance, and developing a much better code base, I have developed a strong gst-sharp player with metadata support.

I am really excited about the rewrite, and new beginnings with the Mono platform. I still love C, but welcome the ease and power of this new platform. It is clearly the new path for GNOME, and I am glad to be a part of it.

The Day of New Stuff: Sonance, SQLite, GOCBuilder

I’m checking in again with some status reports and two new pages on the site. First, I have decided to name my previously mentioned Remix player to Sonance. I am very happy to report that development is going very strong, and I hope to make the first public release by the end of this week. I came to the conclusion that redeveloping yet another GStreamer backend is futile. I have decided to use the GStreamer playback and metadata code from the RhythmBox project. I have also decided to use SQLite as the library database backend. I’ll post with more details when I make the first release.

I am also happy to report that I have written a small article on embedding SQLite within a GNU/Linux autobuild C project. Documentation was not to be found on this matter, and after spending a few hours tinkering with SQLite, I managed to embed the entire engine in Sonance.

Finally, because Sonance is growing rapidly, I was finding myself constantly copying and pasting GObject Class templates from other sources in the project, only to perform many search/replace actions on certain strings to create a new class framework. I decided to take a few hour break from Sonance, and write GObject Class Builder, a very small, ugly Glade/C hack to produce a basic GObject Class template, based on a few levels of input. I added GOCBuilder to my Anjuta Tool Set, and now it’s just a matter of Project|GObject Class Builder, and a few fields to generate a base GObject Class.

That’s all for now. I’ll write next when Sonance makes its debut!

Remix Player: Another GNOME Audio Player

This new project started last week. I’m calling it ‘Remix Player’ for the moment, and currently it reads/writes metadata, plays audio using GStreamer, and can lookup metadata information (fetch album cover images) via an Amazon.com Web Services client I wrote. I’ve never been 100% satisfied with the audio player selection in GNOME. I have somewhere around 5000 songs; my library is comprised mostly of a ripped version of my physical CD collection, all in OGG format. The directory structure where I store my music is organized (Artist Name/Album Name/01. Artist Name – Track Name.ogg).

Before I go into too much depth, I’m just going to say it: I started writing an audio player tailored specifically to my multimedia desires. It will include killer playlist/library management (with separate playlist and library interfaces), an Amazon.com Web Services client to look up additional metadata information (particularly to fetch an album cover image!), and it uses GStreamer 0.8 for audio playback, so whatever GStreamer can play, my player can play.

Because I generally like the concept, I have been using mpd for quite some time. It keeps a database of my music collection for fast metadata searching. My problem with mpd is the lack of a good client front end. I really like gmpc, especially with my mpcstick2 hacks applied, but it’s lacking so many features, particularly good library/playlist organization. Also, due to the client/server nature of mpd, there is much that cannot be implemented (such as visualization plugins) in a client.

Then there’s RhythmBox. It’s cute. Kinda like iTunes. I’ve never been too fond of RhythmBox, though I have much respect for it. It always seems slow, and the interface is too big. It has decent library support, but not really good playlist support. I think it’s good to have a separate playlist and library. I don’t always want to play music directly from my organized library. Sometimes I just want to listen to a standalone media file, without having it merged into the library. RhythmBox does not separate playlist from library. RhythmBox also crashes a lot. I do however like the iRadio support. There aren’t many visual stimulations in RhythmBox either.

That brings me to XMMS/Beep. I haven’t used the legacy XMMS in about a year. I do like the Beep Media Player, which is a GTK2 port of XMMS. It’s basically the same thing. Playlist support in Beep is decent, but there’s no library support. I like the visual stimuilation of Beep, with the skins and nifty bar visualization thing. It also has a straight forward, but basic tag editor, and good plugin support. So I use Beep often for listening to music outside of my complex library.

What I am developing is somewhat of a hybrid of mpd, RhythmBox, and Beep, and I’m mixing in some cool new features that don’t exist in any other program that I am aware of. My goal is strong library support, great playlist support that has the ability of being separate from the library (so I can listen to “standalone” music), metadata searching through various web services (for album cover fetching, concert dates, web sites relating to the band, etc.), visualization effects (like iTunes), a collapsible interface, GNOME tray support, mpcstick2 integration, xosd support, and much more.

So what do you want in an audio player?