|
|
|
|
|
Hildon-ized Zhaan
|
2/26/2010 4:4:07
|
You know how sometimes you just get really excited about a project and put a hold on the rest of life until you get to some point that makes you happy?
Well, once I got Zhaan to run in any shape whatsoever inside scratchbox with the Maemo 5 SDK I had one of those days. I spent a good chunk of my day today hildon-izing Zhaan and the results are really cool. Anderson Lizardo is currently working on making everything work under the ARM target and he intends to post finished .debs within the next day or two. Once those are in extras-devel anybody will be able to run Zhaan on their N900 :)
Some screenshots of the fruit of today's labor:



-Zach Goldberg
|
|
|
|
|
Zhaan working in scratchbox!
|
2/26/2010 0:38:21
|
Step 1 to porting all of my work thus far to the Maemo platform itself is now complete with a (rough) proof of concept: Zhaan working in scratchbox.
Other than some really bad logistical (placement of files, prefix nonsense etc.) hacks I did not have to actually hack at any code at all to take what was working inside jhbuild to work in scratchbox. Sweet.

Victory for tonight.
-Zach Goldberg
|
|
|
|
|
MPD-UPnP Media Serving!
|
2/15/2010 6:46:10
|
Just a quick update on the status of MPD-UPnP. The 1 person who watches my github repo will have already noticed my lastest big push: http://github.com/ZachGoldberg/MPD-UPnP/commit/8a7fce2b4a11e63bc91ae372f6dfcd59beabd7c7 . As of this commit one can start a server from which one can entirely control playback via MPD. Steps 1) and 2) from my previous post are now complete!
Controlling the new MPD server via Zhaan actually works rather pleasantly and bug-free. I am doing most of my work remotely and have Zhaan open via ssh+xorg. My roomates must be freaking out with the music constantly jumping around in my room! I cannot wait to port Zhaan to Maemo 5 and use this from my N900!
-Zach Goldberg
|
|
|
|
|
MPD-UPnP Status update and Generating DIDLLite data with GUPnPAV
|
2/14/2010 3:8:29
|
I have decided that, for now anyway. I am going to substitute my MPD-UPnP project for the Canola GUPnP plugin as part of my project for Penn. If time permits (and I can get Canola to work on my machine, sigh) I will still do the Canola integration.
So, to finish of MPD-UPnP we need the following features:
1) MPD as a Media Renderer of content that MPD already knows about 2) MPD as a Media Server of content MPD already knows about that only MPD can consume
To make this really awesome, we should consider also implementing:
3) MPD as a Media Renderer of arbitrary UPnP-exposed audio content 4) MPD as a Media Server of its own data to other peers.
1) and 2) require simply mapping MPD commands and database content to a UPnP interface. Components 3 and 4 require the wrapper to actually become a full fledged server (to host via UPnP all of MPD's content for 4) and a full fledged proxy (for MPD to use 'downloaded' UPnP content, for 3).
As of now 1) is basically complete. I am working on 2) and have come across the need to generate DIDL data. Before we get into that, lets do a quick overview of how UPnP works for media browsing and serving.
UPnP, at its core, is merely a specification for device discovery (multicast + ssdp), state control (SOAP) and resource access (plain old HTTP 1.0/1.1). The most importaqnt here is the SOAP definitions. What functions should exist? What datatypes are passed? These questions are answered by several pre-defined UPnP specifications, such as a MediaServer (a ContentDirectory) or a MediaRenderer (an AVTransport). The specifications define the functions and arguements to for all of these devices and services.
One can imagine this works very well for simple things. For example, an AVTransport has a function "Play" which takes very few arguments (a speed is oen of the few significant ones). However, for something more complicated, like Browse on a ContentDirectory more than simple argument passing is required. Why? Well, lets say a user asks to Browse some folder foo which has 100 pieces of data. One could simply return a list of filenames, but what about all the other important data for those items? Their UPnP Class, if its audio what the title is, a resource url to download them etc. To solve this problem a DIDL (Digital Item Declaration Language) is used. The result of a Browse call isnt a simple list, its a DIDL. (DIDL is obsentisbly just XML, so the actual datatype that Browse returns is just a string).
So, back to the MPD wrapper. To implement a server we must be able to respond to Browse calls; hence we need to generate DIDL. GUPnP-AV provides a convenient mechanism for doing this. A simple usage looks as follows:
w = GUPnPAV.GUPnPDIDLLiteWriter.new("English") container = w.add_container() container.set_title("Container Title String (a folder name or other)") didl_string = w.get_string()
You'll notice this is rather not-pythonic. The writer keeps an internal reference to the container it returned in add_container such that when you later call writer.get_string() it knows the containers (and items and resources etc.) that it has allocated and how to render them as XML. It is, however, a rather nice API when all is said and done and is thus far working wonderfully for component #2 of MPD-UPnP.
-Zach Goldberg
|
|
|
|
|
Know what your not good at, and don't do it
|
1/30/2010 2:57:25
|
So these past couple weeks I have continued to hack with Python+GUPnP via PyGI. I've pushed some important patches lately, and have even begun making progress in getting the biggest components of my work upstream (woohoo!. GUPnP-AV, GSSDP have been merged. GUPnP itself is 80% the way there, and PyGI is in review).
So, where do I stand on AutoRemote/Zhaan? Zhaan hasn't gotten any love lately and is actually using some older code that I have replaced with much nicer libraries inside AutoRemote.
So, most of my time has gone into AutoRemote (what a crappy name). I am at the point where the UI needs to be written. So I wrote some of it. And its REALLY ugly. And HORRIBLE to use. And I did NOT enjoy writing it. I am happy to say I can recognize what is good UI and what is bad UI, but my own skills to design (and implement!) that good UI apparently don't exist. I think I just proved that P != NP. Awesome.
-Zach Goldberg
|
|
|
|
|
It's Alive -- MPD + UPnP
|
12/22/2009 10:30:57
|
I've put together a (working) quick and dirty script to wrap MPD in a UPnP Media Renderer. This is far from a complete solution, but it allows playing/pausing via UPnP Control Points. (Python-GUPnP CP works just dandy for it!)
from gi.repository import GUPnP, GObject, GLib import mpd
CON_ID = None MPDCLIENT = None
GObject.threads_init()
def setup_server():
ctx = GUPnP.Context(interface="eth0")
ctx.host_path("device.xml", "/device.xml") ctx.host_path("AVTransport2.xml", "/AVTransport2.xml")
desc = "device.xml" desc_loc = "./"
rd = GUPnP.RootDevice.new(ctx, desc, desc_loc) rd.set_available(True)
return rd
def setup_mpd(): global CON_ID, MPDCLIENT HOST = 'localhost' PORT = '6600' CON_ID = {'host':HOST, 'port':PORT}
MPDCLIENT = mpd.MPDClient()
def on_play_action(service, action): print "Play" MPDCLIENT.connect(**CON_ID) MPDCLIENT.play() MPDCLIENT.disconnect()
def on_pause_action(service, action): print "Pause" MPDCLIENT.connect(**CON_ID) MPDCLIENT.pause() MPDCLIENT.disconnect()
rd = setup_server() print "UPnP MediaRenderer Service Exported"
setup_mpd() print "MPD Client Setup"
service = rd.get_service("urn:schemas-upnp-org:service:AVTransport:1") service.connect("action-invoked::Play", on_play_action) service.connect("action-invoked::Pause", on_pause_action)
print "Awaiting commands..." GObject.MainLoop().run()
Update: This is an updated version of the script that supports more commands and properly ends each UPnP action. Unfortunately it doesn't entirely work because of either 1) A bug in g-i or 2) a problem with the gupnp api that will require a break to fix. Spent a lot of time today to understand the problem, hopefully we'll have either a gupnp or a g-i fix in a few days.
Update 2: Now available on github. Zhaan (formerly known as "GUPnP-Python UPnP Control Point" has also been pushed)
-Zach Goldberg
|
|
|
|
|
Pondering MPD and UPnP
|
12/21/2009 9:50:24
|
I had the idea tonight to try and get MPD to act as a well behaved UPnP MediaServer. Low and behold, there exists python-mpd. I smell a new use for GUPnP-Python in the next few days :)
-Zach Goldberg
|
|
|
|
|
GUPnP-Python Control Point Progress
|
12/20/2009 10:50:08
|
Just a brief update. The control point has been making steady progress. I've tested it with a bunch more servers/renderers and its doing fairly well as far as compatibility goes. I've also finished up basic playlist management and some UI quirks (like adding scrollbars).
Next step is to port this guy to Maemo 5 and Hildon-GTK :)

-Zach Goldberg
|
|
|
|
|
Rygel ogg transcoding and the Playstation 3
|
12/20/2009 10:34:03
|
Zeeshan was rather angry at me for putting so much effort into Mediatomb (and rightfully so), so I figure'd I would make him happy and try out Rygel.
Short Summary: Some things work REALLY well (MUCH better than Mediatomb), some things not so well yet. (afterall, Rygel is under much more active development than Mediatomb so any of my gripes could likely be fixed in the near future)
The first problem was getting an up to date version of Rygel. Gstreamer inside jhbuild decided it wasn't interested in loading any of its plugins. Rygel, outside of jhbuild, decided that none of its dependencies would build properly.
It took me 1.5 hours just to get a working version of Rygel compiled. Lame. This, however, would be mitigated by a recent Rygel release and just installing from .deb. So no real marks against Rygel for that.
I then configured Rygel with 2 "Media Exports". My music folder and my movies folder. It then proceeded to spent 15 minutes at 100% CPU scanning my movies.
And it forgot my music :(.
After the initial 15 minutes Rygel crashed because I was missing some gstreamer plugin (shouldn't configure have found that?). Fixed that and rygel finally shows up on the network.
I re-added my music directory without a symlink and this time Rygel loaded it all fine. *shrug*.
I ran over to the PS3 once Rygel had the music categorized and found that, indeed, the PS3 could browse Rygel's collection (to a certain extent... it got an error loading past the 30th item in the list or so. Still trying to find that bug). Anyway, the major point: transcoding worked out of the box for music. No mess, no fuss. Seeking in transcoded streams also worked out of the box. SWEET!
Movies, however, were a different story. I couldn't get any movies to play at all off of Rygel on the PS3. They did, however, work locally when manipulated by my gupnp-python control point.
The one other issue I have is that Rygel doesn't auto-generate folders for meta-browsing like media tomb did. Media tomb would scan all my music and generate some folders such as "Albums" and "Artists" and "All Music" (good for a random playlist) which I could browse on the PS3. No such feature in Rygel yet. (Although the devs say they are open to adding it. Apparently it also works if I use the Tracker plugin. Sadly, however, I don't use tracker on my server).
Overall, the Rygel guys get an A+ for awesome transcoding support for music. The movies issue could also just be a recent bug, as with the showing all items in a large list bug. (Zeeshan says these things should work, so it could just be a regression. I am using git HEAD after all.) I'll also chalk the lack of the meta-folder feature to Rygel still being relatively new software.
Overall very promising. If Rygel didn't have those few bugs mentioned above it would have already replaced Mediatomb and made me a very happy camper. I suspect that these bugs will be fixed shortly and I expect to switch soon :)
-Zach Goldberg
|
|
|
|
You are free to redistrubute
this material under the terms of the Creative Commons bc-nc-sa 3.0 license.
|
|
|
|