Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages | Examples

vos/metaobjects/misc/talkative.cc

Go to the documentation of this file.
00001 /* $Id: talkative.cc,v 1.39 2003/07/23 00:17:27 reed Exp $ */
00002 
00003 /* This file was generated by otd2cpp.pl
00004 
00005     Copyright (C) 2002 Reed Hedges <reed@interreality.org>
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Lesser General Public
00009     License as published by the Free Software Foundation; either
00010     version 2 of the License, or (at your option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Lesser General Public License for more details.
00016 
00017     You should have received a copy of the GNU Lesser General Public
00018     License along with this library; if not, write to the Free Software
00019     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00020 
00021 
00022 */
00023 
00024 #include <time.h>
00025 #include <vos/corelibs/vos/vos.hh>
00026 #include <vos/metaobjects/property/property.hh>
00027 #include "talkative.hh"
00028 
00029 /* initialize static class members */
00030 const unsigned short Talkative::UNSPECIFIED = 0x0;
00031 const unsigned short Talkative::PUBLIC = 0x1;
00032 const unsigned short Talkative::PRIVATE = 0x2;
00033 const unsigned short Talkative::AUTO = 0x4;
00034 const unsigned short Talkative::FROM_APP = 0x8;
00035 const unsigned short Talkative::SYSTEM = 0x8;
00036 
00037 /* Constructors and Destructors */
00038 Talkative::Talkative(MetaObject* superobject) : MetaObject(superobject) {
00039     defaultPropertyAC = &NoPropertyAccessControl::static_;
00040 }
00041 
00042 
00043 LocalTalkative::LocalTalkative(MetaObject* superobject) :
00044     Talkative(superobject), MetaObject(superobject),
00045     replyto(NULL), replynonce("")
00046 {
00047     addMessageHandler<LocalTalkative>("misc:say", this, &LocalTalkative::handle_say);
00048 }
00049 
00050 LocalTalkative::~LocalTalkative() {
00051     if(replyto)
00052         replyto->release(); // acquired in handle_say
00053 }
00054 
00055 RemoteTalkative::RemoteTalkative(MetaObject* superobject) : Talkative(superobject), MetaObject(superobject) {
00056 }
00057 
00058 
00059 /* initialize default PAC */
00060 void Talkative::initialize() {
00061     initialize(&NoPropertyAccessControl::static_);
00062 }
00063 
00064 void Talkative::initialize(PropertyAccessControl* ac) {
00065     defaultPropertyAC = ac;
00066 }
00067 
00068 
00069 /* generator for factory */
00070 MetaObject* LocalTalkative::new_LocalTalkative(MetaObject* so, const string& type) {
00071     LocalTalkative* lt = new LocalTalkative(so);
00072     lt->set_voice(VOS_TALK_NO_VOICE, VOS_TALK_VOICE_DATATYPE);
00073     return lt;
00074 }
00075 
00076 
00077 /* Return type string ("talkative") */
00078 const string Talkative::getType() {
00079     return string("misc:talkative");
00080 }
00081 
00082 /* Register extenders with libvos MetaFactory */
00083 void Talkative::registerExtenders() {
00084     static bool done = false;
00085     if(! done) {
00086     LocalSite::addLocalObjectExtension(typeid(LocalTalkative).name(), &LocalTalkative::new_LocalTalkative);
00087     LocalSite::addLocalObjectExtension(typeid(Talkative).name(), &LocalTalkative::new_LocalTalkative);
00088     LocalSite::addLocalObjectExtension("misc:talkative", &LocalTalkative::new_LocalTalkative);
00089     RemoteSite::addRemoteObjectExtension(typeid(RemoteTalkative).name(), &RemoteTalkative::new_RemoteTalkative);
00090     RemoteSite::addRemoteObjectExtension(typeid(Talkative).name(), &RemoteTalkative::new_RemoteTalkative);
00091     RemoteSite::addRemoteObjectExtension("misc:talkative", &RemoteTalkative::new_RemoteTalkative);
00092     done = true;
00093     }
00094 }
00095 
00096 
00097 /* Get and set Subproperties and other Subobjects : */
00098 
00099 string Talkative::get_voice() {
00100     string s;
00101     rREF(Vobject&, v, findObject("misc:voice"),
00102         Property* p = meta_cast<Property*>(&v);
00103         if(!p) throw bad_cast();
00104         p->read(s);
00105     );
00106     return s;
00107 }
00108 
00109 string Talkative::get_voice_datatype() {
00110     string s;
00111     rREF(Vobject&, v, findObject("misc:voice"),
00112         Property* p = meta_cast<Property*>(&v);
00113         if(!p) throw bad_cast();
00114         s = p->getDataType();
00115     );
00116     return s;
00117 }
00118 
00119 void Talkative::set_voice(const string& value, const string& datatype, PropertyAccessControl* ac) {
00120     if(ac == NULL)
00121         ac = defaultPropertyAC;
00122     LOG("talkative", 5, "setting voice to " << value);
00123     Property::setProperty(*this, "misc:voice", value, datatype, ac);
00124 }
00125 
00126 /* generator for factory */
00127 
00128 MetaObject* RemoteTalkative::new_RemoteTalkative(MetaObject* superobject, const string& type) {
00129     return new RemoteTalkative(superobject);
00130 }
00131 
00132 /* Local Actuators: */
00133 
00134 /* Do say. */
00135 
00136 void LocalTalkative::do_say(TalkMessage& m) {
00137 
00138     if(!listeners.empty()) {
00139         for(ListenerList::const_iterator i = listeners.begin();
00140             i != listeners.end(); i++)
00141         {
00142             if(*i)
00143                 (*i)->notifyTalkMessage(m);
00144         }
00145         return;
00146     }
00147 
00148     // otherwise, just print it out as a log message
00149     string s("[");
00150     bool prevFlags = false;
00151     if(m.scope & PUBLIC) {
00152         s += "PUBLIC";
00153         prevFlags = true;
00154     }
00155     if(m.scope & PRIVATE) {
00156         if(prevFlags)
00157             s += ",";
00158         s += "PRIVATE";
00159         prevFlags = true;
00160     }
00161     if(m.scope & AUTO) {
00162         if(prevFlags)
00163             s += ",";
00164         s += "AUTO";
00165         prevFlags = true;
00166     }
00167     if(m.scope & FROM_APP) {
00168         if(prevFlags)
00169             s+= ",";
00170         s += "INTERNAL";
00171         prevFlags = true;
00172     }
00173     if(m.reply_nonce != "") {
00174         if(prevFlags)
00175             s += ",";
00176         s += " in reply to: " + m.reply_nonce;
00177         prevFlags = true;
00178     }
00179     if(!prevFlags)
00180         s = "";
00181     else
00182         s += "]";
00183 
00184     std::string stime = "";
00185     if(m.time != -1) {
00186         time_t now = time(NULL);
00187         char* ct = ctime(&now);
00188         ct[strlen(ct)] = '\0';  // ctime puts a \n on the end... annoying...
00189         stime = string(" (Sent ") + ctime(&now) + ")";
00190     }
00191 
00192 
00193     LOG("chat message", m.priority, "<" << m.sender.getName()  << "> " << s << " " << m.text << stime);
00194 }
00195 
00196 
00197 /* Send a say message from this object, to whatever object sent us the last message. */
00198 void LocalTalkative::reply_to_last(const string& text, const int priority) {
00199     if(replyto != NULL) {
00200         TalkMessage msg(*this, text, PRIVATE, priority, time(NULL), replynonce);
00201         replyto->do_say(msg);
00202     } else {
00203         throw NoSuchObjectError("Nobody to send reply message to!");
00204     }
00205 }
00206 
00207 /* Send a say message from this object to all children of 'parent' that are talkative. */
00208 ///@todo optimize this. (perhaps use a child listener to world to only store talkative objects...)
00209 void LocalTalkative::say_to_all(const string& text, Vobject& parent, const int priority, const string& replynonce) {
00210     const Vobject::ChildList& children = parent.getChildren();
00211     TalkMessage m(*this, text, PUBLIC, priority, time(NULL), replynonce);
00212     for(Vobject::ChildList::const_iterator p = children.begin(); p != children.end(); p++) {
00213         if(Talkative* t = meta_cast<Talkative*>((*p)->child)) {
00214             t->do_say(m);
00215         }
00216     }
00217 }
00218 
00219 /* Message Handlers:  */
00220 
00221 
00222     /* Handle message say */
00223 
00224 void LocalTalkative::handle_say(Message* m) {
00225 
00226     vRef<Vobject> sender = Vobject::findObjectFromRoot(m->getFrom());
00227     Talkative* t = meta_cast<Talkative*>(&sender);
00228     if(!t) throw bad_cast();
00229 
00230     TalkMessage msg(*t);
00231 
00232     msg.text = m->getField("text").value;
00233     try {
00234         msg.reply_nonce = m->getField("reply-to").value;
00235     } catch(Message::NoSuchFieldError) {
00236         msg.reply_nonce = "";
00237     }
00238     try {
00239         msg.scope = strtoul(m->getField("scope").value.c_str(), NULL, 10);
00240         msg.scope &= ~FROM_APP;
00241     } catch(Message::NoSuchFieldError) {
00242         msg.scope = UNSPECIFIED;
00243     }
00244     try {
00245         msg.priority = strtoul(m->getField("priority").value.c_str(), NULL, 10);
00246     } catch(Message::NoSuchFieldError) {
00247         msg.priority = 0;
00248     }
00249     try {
00250         msg.time = strtol(m->getField("time").value.c_str(), NULL, 10);
00251     } catch (Message::NoSuchFieldError) {
00252         msg.time = -1;
00253     }
00254 
00255     msg.this_nonce = m->getNonce();
00256 
00257     do_say(msg);
00258 
00259     // remember who sent us this message in case we want to reply (note: only works if we are recieving a message from remote objects. but since do_say may be overridden, and never called, we do this here.  we also know the message nonce here.)
00260     if(replyto) {
00261         replyto->release();
00262     }
00263     replynonce = m->getNonce();
00264     replyto = t;
00265     replyto->acquire(); // released on next call to handle_say
00266 
00267 }
00268 
00269 /* Remote Actuators: */
00270 
00271 /* Do say. */
00272 
00273 void RemoteTalkative::do_say(TalkMessage& msg) {
00274     vRef<Message> m = new  Message();
00275 
00276     m->setType("message");
00277     m->setMethod("misc:say");
00278     m->setFrom(msg.sender.getURL().getString());
00279     m->setTo(getURL().getString());
00280     if(msg.reply_nonce != "")
00281         m->insertField(-1, "reply-to", msg.reply_nonce);
00282     m->insertField(-1, "text", msg.text);
00283 
00284     char sc[24];
00285     snprintf(sc, sizeof(sc), "%u", msg.scope);
00286     m->insertField(-1, "scope", sc);
00287 
00288     char pr[24];
00289     snprintf(pr, sizeof(pr), "%u", msg.priority);
00290     m->insertField(-1, "priority", pr);
00291 
00292     if(msg.time == -1)
00293         msg.time = time(NULL);
00294     char tm[64];
00295     snprintf(tm, sizeof(tm), "%ld", msg.time);
00296     m->insertField(-1, "time", tm);
00297 
00298     sendMessage(&m);
00299 }
00300 
00301 
00302 
00303 void Talkative::do_say(const std::string& text, Talkative& sender, const unsigned short
00304 scope, const int priority, const std::string& replynonce, const std::string& thisnonce) {
00305             TalkMessage msg(sender, text, scope, priority, time(NULL), replynonce, thisnonce);
00306             do_say(msg);
00307     }
00308 
00309 
00310 void LocalTalkative::addTalkListener(TalkListener* l) {
00311     listeners.push_back(l);
00312     RefCounted* rc = dynamic_cast<RefCounted*>(l);
00313     if(rc)
00314         rc->acquire();  // released by removeTalkListener
00315         // TODO add excise listener?
00316 }
00317 
00318 void LocalTalkative::removeTalkListener(TalkListener* l) {
00319     bool found = false;
00320     // XXX is this safe to delete like this?
00321     for(ListenerList::iterator i = listeners.begin(); i != listeners.end();
00322         i++)
00323     {
00324         if( (*i) == l ) {
00325             found = true;
00326             listeners.erase(i);
00327         }
00328     }
00329     if(!found) return;
00330     RefCounted* rc = dynamic_cast<RefCounted*>(l);
00331     if(rc)
00332         rc->release();  // acquired by addTalkListener
00333         // TODO: remove excise listener?
00334 }

Generated on Tue Aug 12 03:55:45 2003 for Interreality Project - VOS by doxygen 1.3.2