Groupchat!

Bleah. I've caught my roommate Jen's cold, and so I've felt not much like moving right now. However, I did get enough impetus to sit down and hack away on the Jabber medium a bit more -- yes, even on a weekend -- and have group-chat working. There's one quirk left to fix, but it's an aesthetic bug rather than a functional one.

Yeah, very small update. Not much else to say, other than 'whoot, it works!' Cut me some slack; it's a weekend, and I'm sick today. I'll write something big on Monday. :)
  • Current Music
    Jen curled up on the couch playing Dark Cloud 2

Internals day

Today was really mostly an internals day for the first half. Though I spent some time adding a little feepy thing too, where 'error' is a valid status (if a contact's Jabber server is down, for example) and errored users will have their error message as their status message. This is actually neat, because it means skin authors can add 'error' as a valid status icon, to put a little red exclamation mark over the medium icon or whatever. Also added proper support for a few of the Jabber extensions for various things. Typing indicators, various little nice touches.

Also added a little more to the connection menu, added support for priorities to the resource-picker. This last means it will now properly honor 'priority' fields, allowing a user to determine which of their various connections they prefer to have things go to. If, for instance, I was at home (logged in with resource 'home') and then I went to work (logged in with resource 'work') but I didn't disconnect from home, I could set the 'priority' of work higher to tell people that was where I wanted my messages to go to. In the case of things where there are multiple resources with the same priority, the contact status is used for resolution (i.e. online is preferred over away, away is preferred over extended away, extended away is preferred over DND).

I also added all sorts of internal hooks for later functionality such as service discovery. (Basically, jabber servers can advertise various services using various protocols; I have no UI support for this right now, but I do have the code in place so that internally I can look for various services on various servers.) This will come in very handy when we get to certain later bits!

For the second half of the day, it was spent getting group-chat going. It's /almost/ there, but, alas, not quite; still a couple of quirks to iron out, and I really need to go get dinner before I fall over of malnourishment (which would, after all, hurt my productivity). I was really hoping to have a nice screenshot of group-chat for people, but no. Le sigh. Soon enough, though. :)

<presence><show>away</show><status>Dinner. FOOOOD!</status></presence>
  • Current Mood
    hungry hungry

Screenshot-y goodness!

Well, due to a minor non-work-related crisis last night/this morning, I didn't have time to post a journal update earlier today. So, this evening, you'll get a screenshot as compensation! :)

As for various Jabber stuff, multiple connections are fully pulled through and implemented now, as well as being tested. Typing indicator/offline delivery notification code is in place, so you know when the other party is typing a reply to a message, or if the message has been stored for offline delivery later. The downside is that Jabber typing indicator code works like nothing else; everything else is just 'typing a message' notices (MSN, AIM Direct Connect, etc.) -- Jabber will only send back a 'composing' message to you if you were the last person to type a message. So if I do (where >> means I'm sending it, and << means I'm receiving it from someone else, and ** means some sort of status information...):

>> Hello
** Remote person is typing
<< Hi!
<< How are you doing?
>> I'm good!
** Remote person is typing
<< Great. :)

...as you can see, I don't get typing notifications if they were the last one to do something. This is because Jabber is built around the concept of messages as individual things you reply to, so it only notifies that they're replying to one of your messages. C'est la vie. :)

Groupchat code is in place fully in the backend, and I've begun to pull it through into the UI, so before long all the JDEV folks will have to put up with having a screenshot of that conference room. Hopefully I can get groupchat working tomorrow.

Spammy screenshot graphic, beware!Collapse )

I realize this wasn't as detailed an entry as some...but you got a screenshot! And it was a really busy day today, unfortunately, so I just didn't have time to write up something more in-depth. Hopefully it was still interesting. :)
  • Current Music
    Valeria - Rhythm of The Night

Connection happiness!

Very odd lunch; on the way back from the restaurant, some strange person came over to my roommate Jen and I, and said we were both pretty ladies, and could he be my boyfriend? He hung around for a while basically trying to hit on me, and then went away when the light changed and we were able to cross the street. Hrm. Can I block contacts in RL, please? Or turn on 'only accept messages from those on my contact list?' New plugin idea! RL privacy settings! ;)

Anyway, onto the sort of stuff you actually are reading this for.

Jabber now (almost) fully supports multiple simultaneous connections...the only part that's breaking my brain is the case wherein you get a forced removal on a connection which has a merged contact list. Jabber supports forcing a remote user to remove you from their list; if I receive such a request from a Jabber contact in a merged list environment, I'm not sure how to handle it. If I only remove from the connection that received the 'kill my connection' notice, I will end up sending a re-subscribe request later when the lists next merge. But is simply taking the removal request and doing it for all connections in a shared contact list the best method? Users might prefer it the other way. It works fine as it is with a single connection, or with a connection that has a unique contact list, but a merged list gets kind of tricky...

Food for thought for this evening, I guess. Hooks for message events (things like 'message stored for offline delivery', 'user is typing', 'user stopped typing' and whatnot) are also in place, and I think tomorrow I can get the typing indicator and message delivery notices in place. Then I can start on group-chat; I already have handling for group-chat messaging in the protocol, I just need to actually pull it through to the Trillian API, add lots of nice little menu functions and whatnot to the nicklist, etc.

One thing which is at least making my life easier is that the Jabber medium is written so that you register handlers for things. For instance, I can register a handler for presence events, a handler for message events, a handler for iq events of a particular XML namespace, etc. Even the core functionality is done this way internally, so it's been heavily tested. What's particularly nice, however, is that the handling can be done in plugins. This means a plugin will be able to call into the Jabber medium and register a presence handler, a message handler, whatever.

How is this useful? An example might be for the server-side zebra (black/white) lists...you can block someone at the server-side, using one protocol extension. Let's say I don't implement that in the core functionality (since it's not widely used yet)...maybe someone writes a plugin to implement those lists. This would be possible, as unlike the other mediums, the Jabber one will let you get down at the protocol itself and hook onto any incoming message and respond to it. For the record, I do plan to eventually do just that; implement the server-side white/black lists for Jabber as a plugin with source code, so that others will be able to see how to hook into Jabber functionality.

It's also very useful to me even within the medium, as it means I don't have to make great scary if-then-else trees to handle various sub-options in packets. I just do something like:

RegisterConnect(rosterHelper);
RegisterPresence(rosterHelper);
RegisterIQ(rosterHelper,"jabber:iq:roster");


...and it automatically handles calling 'rosterHelper' when there is first a connection (allowing me to send the request for the Jabber roster), when a presence stanza is received (allowing me to handle online/offline/away/etc notifications and contactlist updates) and when an IQ stanza with a query in the namespace 'jabber:iq:roster' is called (allowing me to catch the actual roster being sent, as well as a few other things). Then 'rosterHelper' is just the routine which handles all the roster-related data for a given connection. Makes my life a great deal easier in code layout!

Anyway, time to save off my code for the evening, make a quick grocery store run, and then relax for the evening. Aah. Must...get...Coca-Cola...!

:)
  • Current Music
    Yuki Kaijura - key of the twilight

Architecture and rearchitecture...!

Ah, one of the best parts of writing a medium for the first time is when you realize you didn't consider one little tiny detail in your architecture, where the code works fine under a single connection but becomes less than usable with multiple connections on the same medium. Needless to say, this comment is prompted by precisely this realization; I made one reasonable assumption about some data in the Jabber roster involving subscriptions...and now, as I begin testing multiple connections to Jabber servers, I discover precisely how my assumption was flawed.

Le sigh.

Luckily, it's something with a fairly obvious change to make. It just means pulling a change through all my Jabber roster management and buddylist interaction code; not difficult, but rather time-consuming. Obviously, this is where my morning has gone; luckily, I've now finished that change, and I need to begin working on a few bits of support code for multiple connections (the Jabber equivalent of the 'Select which connection to send as').

When /that/ is done, I'm going to take a break from contact stuff long enough to play with doing typing indicators (which should really only take about half an hour, most of it adding some stuff into my UI handler) and then I can begin to tackle the last Big Feature I think it needs immediately, which is groupchat. I'm going to implement groupchat-1.0 and then expand up to adding MUC stuff, because I do think the Trillian groupchat implementation should use the MUC JEP.

Unfortunately, I'm in a bit of a frustrating quandry on file transfer; there's an existing file transfer specification, but it's considered pretty well defunct by the JSF...but the new file transfer specification is not completed. Thus, the question becomes, do I add to the problem by adding the old file transfer specification (and supporting file transfer with existing clients, and making users happier) or do the responsible-developer thing and wait, not propagating a defunct specification and adding support for the new file transfer specification when it's more finalized? Decisions, decisions...! What I may do is see if I can come up with a good set of code to support BOTH file transfer specifications, attempting first the good one and then falling back to the older one...

At any rate, saving off an image of my code and heading out to lunch with my roommate. Mm. Food makes the mind clear, and I'm looking forward to getting groupchat in over the next few days. Besides, it's been too long since I had to pester Kevin about UI details; yesterday afternoon, I got so into the backend of my code and away from UI that Kevin had to ask if I was alright...the lack of UI questions and internal API questions had actually worried him!
  • Current Music
    Kenny Rogers - The Gambler

Side notes

...and yes, I will change my layout to something a bit nicer, before long, when I convert this to a paid account. (My real journal on LJ is a permanent account, and I'm big on supporting LJ.)

As a side note, you can add this journal to Trillian Pro's news section, by adding http://www.livejournal.com/users/ceruleansparks/rss to the list of feeds.
  • Current Music
    Prozzak - www.nevergetoveryou

Journal begun...

So, as a long-time LiveJournal user, LJ seems like the best place to put this little blog for the moment. I'm going to keep commentary on current Trillian development here; obviously, I can't give away /everything/ that we're working on, but hopefully this will give some of the users a little more insight into the Trillian development process.

There are a great many things which have been going on behind the scenes without any notice, recently; the next version will have a lot interesting things. Of course, there are many bugfixes and minor improvements...but there are also some fairly major ones.

The big one for developers, of course, is the long-known changes to the plugin SDK for Pro. One of the first things I did was sit down with Kevin and really hashed out a lot of what I as a plugin author had needed in the SDK, and also features that were needed going forward. And I really like what's happened with the SDK; I can get a lot more of Trillian's innards and add a great many more bits of functionality in a plugin, which is a great improvement from my viewpoint. I think my absolute favorite change to the SDK is my most-often-desired one; a way for plugins to define their own API's a'la Trillian Pro's and export them to other plugins. This means someone who writes, say, an encryption plugin could export an API to other plugins; a plugin would be able to test whether or not that encryption plugin was installed, and then call into it.

So, using the new SDK, I've been doing some plugin work to give it a trial run. The first plugin already is done in a beta state, though I need to clean up the preference pages and make it easier to change the user data for it. No, I won't (yet) say what that one is, though I think many people will like it. When we go into beta, I will also be gathering some plugin authors to make a 'plugin beta team' to work on a plugin or two together (with my help/handholding over new API stuff as needed) in order to beat on areas of the SDK I may have missed.

However, the much bigger project for me at the moment is one that eclipses that. What I've been working on for a while now is a Jabber medium. Yep, that's right...we're getting Jabber! (As those poor saps unfortunate enough to have my on-again-off-again Jabber address on my test server on their rosters have undoubtably noticed by now! I feel faintly sorry for Bart...) The medium is already functional at the basic level; you can add and remove contacts, subscribe/deny, all the other useful roster stuff. It responds to most standard client-to-client IQ queries (version, time, etc.) and handles roster in the contact list and general messaging.

Jabber forced a change in how the contactlist works, as well; metacontact functionality is more general, now. A medium can define a metacontact-like contact in the list, and create 'subcontacts' under it (though unlike metacontacts, subcontacts cannot be dragged in or out of their parent). The Jabber medium uses this to display when a contact has multiple resources on, which can be talked to directly. For instance, 'rcb' might be on as both a 'Trillian' resource and an 'Exodus' resource; the user can either interact directly with the 'Trillian' resource or the 'Exodus' one, or allow Trillian itself to decide which to talk to based on presence priority and resource status.

Of course, the Jabber medium also has a fair way to go. I have various elements of UI to clean up (handling multiple Jabber connections properly being the big one), various base functionality to add (groupchat is the big one here) and a LOT more testing to do and a bit of overall aesthetic and functional cleanup (like, actually making the account addition and preference pages not look horrible, probably supporting JUD for add-a-user, etc.). However, I'm very happy with how it's coming out so far!

Even still, the first cut of the Jabber medium will be fully functional for the base set but probably won't implement overly many of the JEPs, just so as to get it done and out the door in a usable state. However, a lot of effort will be put into it over the future; the overall end goal for the medium is to bring the Jabber medium to the point that all the features of other mediums are supported within it. Ideally, we would then move beyond that mark to make Jabber the most-featureful of the mediums. That would, hopefully, give Jabber itself a fairly significant boost; Trillian users would be able to move to using Jabber for their primary medium without a loss of features, making it fairly painless.

Whew. Well, a sort of spammy first update to bring everything current, but hopefully it makes for interesting reading. :)
  • Current Music
    BoA - Every Heart