User:Which Linden/Office Hours/2008 Sep 25
Jump to navigation
Jump to search
- [11:03] Which Linden: hey sai
- [11:04] Which Linden: how ya doin?
- [11:05] Saijanai Kuhn: hey which was afk
- [11:05] Saijanai Kuhn: Doing LK
- [11:05] Saijanai Kuhn: OK
- [11:05] Which Linden: :-)
- [11:06] Which Linden: How's life been?
- [11:06] Saijanai Kuhn: Wanted to pick your brain for a sec. Maybe get a pointer where to look
- [11:07] Saijanai Kuhn: I'm doing a GUI for pyogp, and I'd like to create a nice, standardized message handler so that we can use it for variouss purposes from a standlaone client to a multi-av testharness
- [11:08] Saijanai Kuhn: so I'm thnking there are various kinds of messages that would be passed. Packets, and uesr events being the 2 main categories I think
- [11:08] Which Linden: Message handler .. like a programmatic way for external applications to communicate with a running pyogp client?
- [11:09] Saijanai Kuhn: right or a GUI
- [11:09] Saijanai Kuhn: either integrated or external, or a command file
- [11:09] Which Linden: Ah ... so the pyogp client would be controlled by messages only , and one possible sources of messages would be the GUI
- [11:09] Saijanai Kuhn: right. I'm an applescript fan
- [11:09] Which Linden: (just stating what I think you're saying so I can be clear)
- [11:09] Which Linden: ok
- [11:10] Which Linden: well...we've been talking about how cool it would be to have an HTTP server in the client
- [11:10] Which Linden: (not seriously, just a thought)
- [11:10] Saijanai Kuhn: so, as I see it, there are two basic categories: user events and internal events like packet data and the like. Both can use the same pipeline
- [11:11] Saijanai Kuhn: well, that was one of my ideas from a whle back. Have a bunch of separate pyogp processes with multiple avies for each process, and use reverse http to establish a command stream with a central GUI or other controller
- [11:11] Which Linden: To be clear, user events = things like movement, click on this object, etc
- [11:12] Saijanai Kuhn: right. Chat, manipulation of inventory, movement, TP, etc
- [11:12] Which Linden: I'm not so clear on what internal events would be. Textures, object data, that sort of thing?
- [11:13] Saijanai Kuhn: yeah, at the least, the ability to pass packet data around to internal handlers
- [11:14] Saijanai Kuhn: So, up until this instant I thought one pipeline could handle everyting, but then realized that there would be a security/confusion issue wth directly calling internal handlers through the same pipe as the user comands.
- [11:15] Saijanai Kuhn: should have a way to evoke internal handlers, but not directly. OTherwise you could do nasty stuff, either deliberately or by accident
- [11:15] Which Linden: I think conceptually it would be a lot simpler to think of this as an application that happens to present a programmatic API
- [11:16] Saijanai Kuhn: well...
- [11:16] Which Linden: Cause you want the app to be handling nearly everything, and things using the API just want to effect some change
- [11:16] Saijanai Kuhn: rather than publishing a bunch of hooks, just have one message handler that accepts a an event/data format
- [11:17] Which Linden: But how's that any different? Doesn't that just push the problem down to publishing the list of event/data pairs that it supports?
- [11:18] Saijanai Kuhn: sure, but allows handling of the comands from one cetnral location, so you could log each comand as it comes in or filter it or whatever
- [11:18] Saijanai Kuhn: also lets you just POST to a client from a central controller
- [11:19] Saijanai Kuhn: if you implement the reverse http server thing, or a comet long poll
- [11:20] Which Linden: Well... you can have a centralized transport
- [11:21] Which Linden: It seems that having an HTTP server in the client addresses everything we've been talking about
- [11:21] Saijanai Kuhn: right, though, wouldn't strictly be necessary for a integrated GIU. Could talk directly to the message handler if need be
- [11:22] Hinnerk Allen: Hello
- [11:22] Which Linden: Greetings
- [11:23] Saijanai Kuhn: Hey Hinnerk
- [11:23] Hinnerk Allen: how are you?
- [11:23] Saijanai Kuhn: doing fine. What's up?
- [11:23] Which Linden: What do you mean by "the message handler"? Isn't a message handler typically just a function?
- [11:24] Saijanai Kuhn: well, I guess the event handler
- [11:24] Hinnerk Allen: just popped in zhis place and like to look around
- [11:25] Which Linden: Well, enjoy yourself!
- [11:25] Which Linden: I haven't put up much in the way of elaborate structures here
- [11:25] Which Linden: All this bamboo really kills my prim limit. Need to learn how to use sculpties
- [11:26] Saijanai Kuhn: this was my quick and direty handler class: [1]
- [11:27] Saijanai Kuhn: not meant to be the real thing, just so I can discuss the concept
- [11:28] Saijanai Kuhn: python has this fun thing where you can treat an object as a method if you use __call__ so a handler could be a function, a method OR a complete object wth state
- [11:28] Which Linden: In Python you can just assign methods to an object -- so why not just do myeventhandler.anothermeth = anothermeth("boo!") ?
- [11:31] Which Linden: So.... just IMO, it makes sense to set this up as a url hierarchy in the client.
- [11:31] Saijanai Kuhn: well, hmmm... not sure how that works, exactly. I want to pass a logout command to the client from the GUI or whatever
- [11:31] Which Linden: OK, that's a good example
- [11:32] Which Linden: We want some way for an external application to tell pyogp, "log out your agent"
- [11:32] Saijanai Kuhn: or for the error handler to undo the login because it got an error
- [11:32] Which Linden: So.... if that was an HTTP service you could set it up as a PUT [2] with an empty body
- [11:33] Which Linden: I ... error handler?
- [11:34] Saijanai Kuhn: well, take what happened ysterday. I ran my GUI login client against the wrong protocols and it barfed a few seconds in . Got nice error messages, but it kept trying to continue my login process. Should have a way to insert a "cancel login" message into the stream when that happens
- [11:35] Which Linden: I guess.... but it also seems like a "do not retry" flag might address that just as well
- [11:35] Which Linden: I mean, as a preference
- [11:35] Saijanai Kuhn: well, what about all the nasty bookkeeping to reset the client? Rather not quit the process and startover.
- [11:36] Which Linden: Yeah, but the client itself can't even do that
- [11:36] Saijanai Kuhn: just reset all the objects to a client state and wait for a new command
- [11:36] Which Linden: Er... I mean the viewer can't unlogout
- [11:36] Saijanai Kuhn: well, the SL client is a pisspoor design in many ways, IMHO
- [11:36] Which Linden: Fair enough
- [11:37] Tegg Bode: Hi , umm where is everyone, is there a black plague happening or something?
- [11:37] Which Linden: I guess the danger in presenting too much control to external applications is that your client then guts itself
- [11:37] Which Linden: Hi Tegg
- [11:37] Which Linden: I dunno! Presumably people come when Sai sends out group messages about the hours?
- [11:38] Saijanai Kuhn: so, as I see it, you're binding yoruself to a SL-centric view of how clients work. I can see how url-based commands might be a way to implement it, but its still a matter of having commands that don't expect a pure SL model
- [11:38] Saijanai Kuhn: was AFK during my spam period
- [11:38] Which Linden: Hah
- [11:38] Tegg Bode: lol
- [11:39] Which Linden: It's fine, I don't mind less folks, kind of a chill-out in that case
- [11:39] Which Linden: Tegg, just to catch you up, we're discussing what sort of programmatic API should pyogp expose
- [11:39] Saijanai Kuhn: Which, too much control can be compensated for by having the internal/external command handler. the internal command handler accepts any commands, the external only accepts a subset, or flags them as coming from an external source in some way
- [11:40] Saijanai Kuhn: well, I am not sure I'm talking about that specifically, except that this could handle both internal message passing AND user commands usign the same general design
- [11:41] Saijanai Kuhn: like I said, I'm a big fan of AppleEvents, which is what I'm modeling this on, to some extent
- [11:42] Which Linden: Yeah..... so what you want is basically a way for other apps to register for listening in on what the client is doing, and a way for them to poke it to make it do something different
- [11:42] Saijanai Kuhn: the object model of AppleEvents is basically user-oriented behavior. Quit, login, send chat, select object
- [11:42] Saijanai Kuhn: right
- [11:42] Which Linden: AppleEvents have a somewhat different model because most apps are event-driven, not streaming like SL
- [11:43] Saijanai Kuhn: though for the test harness version, you could also apply raw packets and request that they be sent
- [11:43] Saijanai Kuhn: well, yes, but the user GUI is event driven
- [11:43] Which Linden: Not to say that the model couldn't be applied, but it would, in many cases, be a bit of shoehorning
- [11:43] Which Linden: Yeah -- ok
- [11:44] Which Linden: I still think HTTP is fine for this use case. If the client wants to receive the event stream, reverse http or long poll
- [11:44] Saijanai Kuhn: User selects a menu. User clicks on an object. User manipulates an inventory item...
- [11:44] Tegg Bode: Cool, most of it above my head but I listen anyway :)
- [11:44] Saijanai Kuhn: sure, but for an integrated API, would be kinda overkill
- [11:45] Saijanai Kuhn: What I want to see is a separattion of things so that the GUI can post events directly to teh event handler, not post them to the local host.
- [11:45] Which Linden: Overkill? Well -- here's the thing: no matter what, unless the OS provides some sort of special framework, you're always going to be talking to an app over a pipe
- [11:45] Which Linden: And so you have to have some sort of serialization over that pipe
- [11:45] Which Linden: HTTP is one possibility, presumably AppleScript uses its own
- [11:46] Saijanai Kuhn: well, for any external app, sure. But is it worth it to insist that each GUI element POST an event to local host?
- [11:46] Which Linden: Well.... if the GUI is not running in the same process as the client, then it has to get that message there somehow
- [11:47] Which Linden: And a POST is not especially different from any other way
- [11:47] Saijanai Kuhn: right. I guess I'm trying to see if the URL semantics are the way to go, even for the integrated GUI
- [11:48] Which Linden: I should say that I really don't know very much about platform-specific IPC, I really just know about pipes and sockets
- [11:48] Saijanai Kuhn: like I said, you have the case where my pyogp client tries to continue the logiin because I don't have an error handler to say "cancel login"
- [11:49] Saijanai Kuhn: OK I guess this is higher level stuff I am thinking of.
- [11:49] Saijanai Kuhn: how would you send a quit message to the client using the URL strategy you've been talkign about?
- [11:49] Which Linden: You gotta refactor your client to check its "cancel login" handler periodically anyhow
- [11:50] Which Linden: Like, the login procedure has a bunch of if not CANCEL_LOGIN: scattered through it
- [11:50] Which Linden: and then you just put up an url, [3]
- [11:50] Which Linden: and if the client puts FALSE there, then the if statements catch it, and bail
- [11:51] Saijanai Kuhn: ah, OK. Well that could work. THough, I suspect it could be a bit more elegant than that
- [11:51] Which Linden: It's possible -- I definitely have a very different worldview
- [11:53] Saijanai Kuhn: When I was refeactoring the login example code, I created a little decorator that would go in front of each segment of the login and place the methods in a list. Then you could call them in a thread or an idle/timer event loop for GUI control OR in a tight loop to simulate the original monolithic login code
- [11:53] Which Linden: Refactoring the login code as a series of method calls?
- [11:53] Saijanai Kuhn: could have the relevant state checking added in that generic loop code instead of sprinkling it everywhere
- [11:53] Which Linden: Yeah, definitely that would be more elegant
- [11:54] Saijanai Kuhn: right.. A login class to maintain state, and meth1()meth2() etc
- [11:54] Which Linden: Yeah, that's a better design than the ridiculous thing currently in the viewer
- [11:54] Which Linden: Yeah -- so then you would just expose the state of that class via REST ... and, boom!
- [11:54] Saijanai Kuhn: so I just put the @adtolist(alist) decorator in front of each method that needs to be tracked
- [11:54] Which Linden: Steve Jobs would show up
- [11:56] Saijanai Kuhn: so the cancl login method would just check the curent state of the login object, and reset itself and all relevant stuff that may have happened outside the class
- [11:56] Which Linden: Yeah, that sounds like a pretty clean way of doing things -- be careful with concurrency though
- [11:57] Saijanai Kuhn: tight. For the wx windows, I'm doing everything oustide the loop and posting events to wx via the callafter event thing. Which makes it threadsafe
- [11:57] Saijanai Kuhn: outside the main wx thread*
- [11:57] Which Linden: OK
- [11:57] Saijanai Kuhn: also means I don't have to worry toomuch about thread desig which is a very good thing since this is the first time I've used threads
- [11:59] Saijanai Kuhn: found a nice example of how to print to the wx text panels that no-one seemed to be using. just make a textpanel a file-like object with a write method that uses callafter.
- [11:59] Saijanai Kuhn: they use it in their built in error logging window, and no-where else I could find
- [11:59] Which Linden: Hmm.... that's neat
- [12:00] Saijanai Kuhn: so I took tao's logger code and directed it to the error text panel instead of stdio
- [12:00] Saijanai Kuhn: works like a charm
- [12:01] Which Linden: nice!
- [12:01] Which Linden: I love it when things just work out like that
- [12:01] Saijanai Kuhn: doesn't understand threading, but has been working with oop and GUI for over 20 years ;-)
- [12:02] Which Linden: Threading doesn't seem to be taught, it seems to be beaten into you
- [12:03] Which Linden: I should run.
- [12:03] Saijanai Kuhn: so anyway, I guess for something like url:login/cancel. The GUI could post the event login/cancel:{}
- [12:03] Saijanai Kuhn: how would the URL work for an event with data?
- [12:03] Which Linden: POST body?
- [12:04] Which Linden: From what you're saying it sounds like the GUI is in the same process space -- I'd thought at the beginning of this discussion that it was not
- [12:04] Saijanai Kuhn: OK, so class/sublass:{blahblah}
- [12:04] Saijanai Kuhn: right, well I'm trynig to make this generic to both
- [12:04] Saijanai Kuhn: same process space for the prototype I'm working on. A differnt process space for a molre elaboriate setup
- [12:04] Which Linden: You can definitely short-circuit the HTTP chain
- [12:04] Saijanai Kuhn: righ, wanted to keep things as simple as possible
- [12:05] Which Linden: So that, say, instead of the GUI doing a full POST it just does http_handler(path, body)
- [12:05] Which Linden: and when an actual POST comes in, it eventually ends up at http_handler too
- [12:05] Saijanai Kuhn: right where path is the part after the port number in the url
- [12:06] Saijanai Kuhn: OK, that would work just fine
- [12:06] Which Linden: :-)
- [12:06] Which Linden: Happy refactoring, buddy, I'll catch you later.
- [12:06] Saijanai Kuhn: so instead of event:blah it would be http_handler(path, blah)
- [12:06] Saijanai Kuhn: great thanks for the discussion
- [12:07] Which Linden: Thanks for sharing!
- Which Linden