00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
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();
00053 }
00054
00055 RemoteTalkative::RemoteTalkative(MetaObject* superobject) : Talkative(superobject), MetaObject(superobject) {
00056 }
00057
00058
00059
00060 void Talkative::initialize() {
00061 initialize(&NoPropertyAccessControl::static_);
00062 }
00063
00064 void Talkative::initialize(PropertyAccessControl* ac) {
00065 defaultPropertyAC = ac;
00066 }
00067
00068
00069
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
00078 const string Talkative::getType() {
00079 return string("misc:talkative");
00080 }
00081
00082
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
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
00127
00128 MetaObject* RemoteTalkative::new_RemoteTalkative(MetaObject* superobject, const string& type) {
00129 return new RemoteTalkative(superobject);
00130 }
00131
00132
00133
00134
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
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';
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
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
00208
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
00220
00221
00222
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
00260 if(replyto) {
00261 replyto->release();
00262 }
00263 replynonce = m->getNonce();
00264 replyto = t;
00265 replyto->acquire();
00266
00267 }
00268
00269
00270
00271
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();
00315
00316 }
00317
00318 void LocalTalkative::removeTalkListener(TalkListener* l) {
00319 bool found = false;
00320
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();
00333
00334 }