Following on from yesterday, I needed to pass arguments to the window being opened. The data I needed to pass was quite simple, so I simply serialized it to JSON and then passed them as strings in a nsICollection (actually, a @mozilla.org/supports-array;1 collection of @mozilla.org/supports-string;1) and then just eval()’d the data within the xul window’s javascript.

This is a bit of a hack, but its probably the simplest way of passing structured data. What would be nice is a bit of code that would automagically serialize a bean to JSON notation… I’m sure there are many out there (This apache struts class looks promising)

Finally worked this out…

These pages are rather helpful: Mozilla’s guide to using proxies and XulPlanet’s description of the nsIProxyObjectManager

This interface defines a proxy manager. An instance of this manager is used to create a proxy for a particular object on which you wish to invoke a method. If you are calling from any other thread that which you initialized xpcom on, you will need to do this, and as far as I am aware, there is no trivial way of doing otherwise.

Anyway, the code to open a new window would be as follows. Note, this method assumes that there is already a constructed object called windowWatcher, which is an instanceof nsIWindowWatcher, see previous post for details.

 public void openWindow(String chromeUri, String name) {
nsIEventQueueService eventQueueServive =
(nsIEventQueueService)serviceManager.getServiceByContractID(
"@mozilla.org/event-queue-service;1",
nsIEventQueueService.NS_IEVENTQUEUESERVICE_IID);

nsIEventQueue eventQueue = eventQueueServive.getSpecialEventQueue(
nsIEventQueueService.UI_THREAD_EVENT_QUEUE);

nsIProxyObjectManager proxy =
(nsIProxyObjectManager)componentManager.createInstanceByContractID(
"@mozilla.org/xpcomproxy;1",
null,
nsIProxyObjectManager.NS_IPROXYOBJECTMANAGER_IID);

nsIWindowWatcher windowProxy =
(nsIWindowWatcher)proxy.getProxyForObject(
eventQueue,
windowWatcher.NS_IWINDOWWATCHER_IID,
windowWatcher,
nsIProxyObjectManager.INVOKE_SYNC );

windowProxy.openWindow(null, chromeUri, name, "centerscreen", null);
} 

The code here uses the service manager to get an instance of the event queue manager, which is subsequently used to retreive the main UI event queue. This is then passed to the proxy manager’s getProxyForObject method, along with the IID of the nsIWindowWatcher interface, the actual instance, and flag representing the type of proxy operation (async, sync, etc, see the xulplanet page for more info).

This method returns an instance of nsIWindowWatcher, which is actually a proxy which will inject events onto the UI thread for you. Then, just use the object as normal, sweet!

After poking around for some hours (then days) trying to find some useful information on how to use JavaXPCOM (which is a bridge between XPCOM and Java, formally known as Javaconnect) I stumbled across a few things as well as hacking together some understanding myself and through C++ examples of XPCOM usage.

We decided a while back to adopt an XML based protocol wherever possible, and moreover, RDF where appropriate. When communicating with a central server, this would use HTTP, so it seemed logical to use the same on the localhost. So, XUL uses AJAX, basically, to do asynchronous calls over HTTP to localhost, and retreives XML which is then passed into objects representing the returned resources. This way, we dont need to heavily integrate Java and XUL using XPCOM, and we allow other applications to be able to place nicely with the API over a well-known protocol and format. Anyway, this means that the only work JavaXPCOM needs to do is:

  • Start XPCOM using a XULRunner installation
  • Start an XUL window and pass control over to it
  • Be able to call javascript/xul events from java (to open windows, etc)

So to start with, we need to find an XULRunner install. As it stands, we will distribute a version with the installer, but JavaXPCOM contains code to easily find installed versions as well (this is actually documented on the JavaXPCOM site).

  1. Set the path the XULRunner directory, here we are doing it explicitly:
    File grePath = new File(new File(".").getAbsolutePath(), "platform/win32/xulrunner");
  2. Next create an instance of the LocationProvider
    LocationProvider locProvider = new LocationProvider(grePath);
  3. Initialize JavaXPCOM embedding:
    Mozilla.getInstance().initEmbedding(grePath, grePath, locProvider);
  4. Now we need to start an XUL application, so we get an instance of the XPCOM service manager
    nsIServiceManager serviceManager = moz.getServiceManager();
  5. Now we need to get the @mozilla.org/toolkit/app-startup;1 service:
    nsIAppStartup appStartup = (nsIAppStartup)serviceManager.getServiceByContractID("@mozilla.org/toolkit/app-startup;1", nsIAppStartup.NS_IAPPSTARTUP_IID);
  6. Get the nsIWindowWatcher interface to the above
    nsIWindowCreator windowCreator = (nsIWindowCreator)appStartup.queryInterface(nsIWindowCreator.NS_IWINDOWCREATOR_IID);
  7. Get the window watcher service
    nsIWindowWatcher windowWatcher = (nsIWindowWatcher)serviceManager.getServiceByContractID("@mozilla.org/embedcomp/window-watcher;1", nsIWindowWatcher.NS_IWINDOWWATCHER_IID);
  8. Set the window creator (from step 6)
    windowWatcher.setWindowCreator(windowCreator);
  9. Create the root XUL window:
    nsIDOMWindow win = windowWatcher.openWindow(null, "chrome://your-app/content/window.xul", "mywindow", "chrome,resizable,centerscreen", null);
  10. Set this as the active window
    windowWatcher.setActiveWindow(win);
  11. Hand over the application to xpcom/xul, this will block:
    appStartup.run();

Now, the LocationProvider is responsible for providing path(s) and file(s) that XPCOM needs. I have implemented a version that when the ‘ChromeML’ location is asked for returns an array of File’s, the first of which points to my own applications chrome folder, and the second of which is the xulrunner’s own chrome folder. This seems to work, but there are several issues:

  1. I do not seem to be able to open XUL windows (or in anyway interact with xpcom/xul) from another thread. Since this run() method on nsIAppStartup blocks, this is a bit annoying. I presume there is a way to run this loop manually, or hook into it so we can queue up requests from other threads to be invoked on the xpcom thread.

Ok, thats only one major issue for now, but I’m sure I will think of others.
If anyone has any ideas how these problems can be solved, or how one may circumvent them, I’m all ears. Also, I know that this area is so bleeding edge it hurts, so it would be nice to talk to some other people doing the same things!

Development, XUL @ 10 February 2006, “No Comments”

Just a quick roundup of some interesting developments I’ve seen recently in the world of persuing elegant cross-platform solutions for media players.
Songbird is a media player in the vein of iTunes that uses XUL

http://xullicious.blogspot.com/2005/06/xul-music.html  is an example of how to make a cross platform media player using gstreamer and directx for the application, and XUL for the front end.

Zap! is a XUL based SIP (ie, VoIP) client for mozilla.  Basically a cross-platform streaming audio tool using the PortAudio audio library.

Development, DotNet, XUL @ 20 December 2005, “No Comments”

Our choice of platform for MixIndex was .NET/C# since it was, at the time, going to be tightly integrated and specific to the Windows OS. However, with the pace of development of Mono and PortableDotNet over the last couple of years, most of the app will now run on any platform. Two key components, however, do not.

First, is the streaming audio library, DirectX is used on windows, but since this is quite well abstracted, it could be rewritten on a per-platform basis, not the best solution, but it is doable.

Second, however, is the UI, System.Windows.Forms is an ugly beast, and not supported very well by either of the two open-source dotnet runtimes, so a choice needs to be made.

After looking at WX.NET, a .NET implmentation of WX widgets, and GTK#, GTK+ bindings for .NET, I was begining to get dishartened by the hackish way they were all implemented. GTK# is just ugly on all platforms, rather than looking good on one or two. WX uses the native interface, but there are no decent, free/cheap, tools to help you, the ones that do are so clunky, they make me worried as to how the rest of the system is imlpemented. All in all, very underwhelming.

Anyway, I am now looking at XUL and its damn nice, clean, standards complient, cross platform and open-source. The XUL Runner is a standalone application for running XUL apps, which would be packaged into the apps installer, and then the XUL part can communicate with the ‘real’ application over SOAP, XML RPC, or whatever, enforcing a strict seperation of UI and Application. Stuff like localization is done through entities defined in DTDs, and styling is done through css, very very cool.

This is the tutorial I followed.

Development @ 19 December 2005, “No Comments”

Just a thought, wouldn’t it be nice if you could agregate rss feeds for events, and filter by location. Therefore, when I’m in Seattle in January, I could instantly see whats going down in the area, and when i return to the UK, I would then again see details for events in the London area.

Its quite interesting that the marketing world is begining to pick up on this, I for one would quite like an RSS feed from ticketmaster, say, complete with community tagging, so i could just get a feed of stuff I’m interested, based on my current location. The transition from being an irritating, ever-present, lowest-common-denominator-targeted, to useful, informative, open and transparent will make the early adopting marketing firms very very rich, they just need to become the first point of contact for such things.

No doubt, this will be Google; “Tell us your events on google base, and people can search based on their current location!”… Oh wait, isn’t this already possible?

DRM @ 18 November 2005, “No Comments”

Interesting article on Wired about the Sony We-Hate-Our-Customers fiasco:

http://www.wired.com/news/privacy/0,1848,69601,00.html

This makes me think (read: hope) that the future of DRM is a rather gloomy affair, based around mutual distrust between the consumers and the distributers, with the content creators cast to the sidelines.

Why cant they just embrace the inevitable and use it to their advantage? Surely the first to ‘Get It’ will go on to be very successful? The major expense for the record companies is the packaging, distribution and marketing of the material, not its actual production.  The internet, and perhaps more specifically, p2p removes this expense, in fact people will give up their own time/bandwidth to distribute the material for you.

The problem is about reimbursing the content creators for their hard work, but surely this can operate independently from the distribution? Why not adopt a model similar to TV or radio advertising where viewer/listener figures, and thus the revenue to be generated by the ads, is determined by statistically analyzing focus groups and sample households. This obviously isnt perfect, but another thing that the p2p networks gives us for free is statistics on searches and downloads (until they become darknets that is).

Just ask everyone to pay £50/year, or something, like a tv license, and this gets divided up between the agents representing the artists. Most will pay, but those that don’t are still giving something in their free distribution, archiving and ripping of material.

Ok, so its not perfect, but its better than installing spyware on your customers’ computers :P

Development, PHP @ 26 October 2005, “No Comments”

Zend have, finally, realised that enterprise and even just larger scale PHP projects, require more than just PEAR, PHP5 and Zend Studio, whilst all good, what they lack is coordination and a sense of the ‘Bigger Picture’.

Just as Java has its Community Process, PHP will now have a collaboration process where industry and the community can together work towards defining a web application framework and deployment system. This is really good news for anyone that writes site larger than a few pages, and especially when you work on many projects, quite often doing the same things again and again. Most seasoned PHP programmers have their own frameworks they use to make life a little less mundane and build on past tried-and-tested code. PEAR was a good effort to get people working on reusable components, but this is all PHP4 based and lacks an overall framework for implementing these components within.

My own framework consists of:

  • a Java based core API – java.io, java.net, java.util, java.lang, etc (I am intending to merge this with cucua.tigris.org)
  • a runtime library – class loader, error handling, logging, configuration, etc
  • a servlet container – based on the Java Servlet 2.4 specification
  • a MVC framework – based on Struts
  • a component framework – based on Tapestry

When I can find a free Subversion open-source provider, and a name, I will make all this available under some sort of generous license (LGPL?) in the hope that perhaps some of it could be of some use to some people, and perhaps even to the formation of the official webapp framework.

Anyway, more here: http://www.zend.com/collaboration/

Development, PHP @ 26 October 2005, “No Comments”

RSS + BitTorrent is gradually emerging, its only a matter of time before the two become indistinguishable.

iPodder (a cross platform podcast client) has already gained bittorrent support, and I guess clients like µTorrent and BitComet will also eventually support RSS.

This basically allows us to have all the immediacy of RSS with the low/fair bandwidth model of BitTorrent; suddenly mass distribution of all kinds of content becomes very simple.

Obviously, lots of services (some exist already) will start to offer dubious torrent-rss of popular TV shows and such like, but what I would like to see more than that is news. Good quality news, like the BBC, up to date, on my desktop (and therefore onto my phone/pda/ipod etc).

I have written a simple PHP script that goes off and parses the BBC site and pulls down the asx (ie, wmv) video, runs it through mencoder and convert it to mp4/mp3. All I would need to do then is create the torrent files and then publish an RSS feed… but not much point until there is a client available.

Ajax, Development @ 22 October 2005, “No Comments”

Ajax is damn cool.

I am currently working on a small project using Google Maps which displays properties on a map. There is a central object which manages communication (via googles GXmlHttp) with the servers-side php. Upon response, this same object parses the response XML and then updates its observers.

Each component then has an object which manages its display, it subscribes to the main object, and upon update will redraw that elements innerHTML, mostly by transfrorming the responseXML with XSLT using googles GXslt class).

This got me thinking about a component base widget framework implemented in javascript, something that a server side application could easily communicate with. Imagine something like awt/swing being rendered to a javascript/html browser, rather than a normal windowing system. Upon an event, the component would send the event object back to the server, the server would process this, and update all components subscribed to the model, the components would then decide whether they need to be redrawn or not, and the new state of these components would be collected, packaged up in xml, and sent back to the client.

This would mean that only the components that change would need to be updated and redrawn, and the whole page need not be reloaded.

A quick poke around found a couple of interesting projects: