// DO NOT EVER INCLUDE THIS HEADER FILE YOURSELF #ifndef __lcm_cpp_impl_ok__ #error "Don't include this file" #endif // =============== implementation =============== int Subscription::setQueueCapacity(int num_messages) { return lcm_subscription_set_queue_capacity(c_subs, num_messages); } template class LCMTypedSubscription : public Subscription { friend class LCM; private: ContextClass context; void (*handler)(const ReceiveBuffer *rbuf, const std::string& channel, const MessageType*msg, ContextClass context); static void cb_func(const lcm_recv_buf_t *rbuf, const char *channel, void *user_data) { typedef LCMTypedSubscription SubsClass; SubsClass *subs = static_cast (user_data); MessageType msg; int status = msg.decode(rbuf->data, 0, rbuf->data_size); if (status < 0) { fprintf (stderr, "error %d decoding %s!!!\n", status, MessageType::getTypeName()); return; } const ReceiveBuffer rb = { rbuf->data, rbuf->data_size, rbuf->recv_utime }; subs->handler(&rb, channel, &msg, subs->context); } }; template class LCMUntypedSubscription : public Subscription { friend class LCM; private: ContextClass context; void (*handler)(const ReceiveBuffer *rbuf, const std::string& channel, ContextClass context); static void cb_func(const lcm_recv_buf_t *rbuf, const char *channel, void *user_data) { typedef LCMUntypedSubscription SubsClass; SubsClass *subs = static_cast (user_data); const ReceiveBuffer rb = { rbuf->data, rbuf->data_size, rbuf->recv_utime }; subs->handler(&rb, channel, subs->context); } }; template class LCMMHSubscription : public Subscription { friend class LCM; private: MessageHandlerClass* handler; void (MessageHandlerClass::*handlerMethod)(const ReceiveBuffer* rbuf, const std::string& channel, const MessageType* msg); static void cb_func(const lcm_recv_buf_t *rbuf, const char *channel, void *user_data) { LCMMHSubscription *subs = static_cast *>(user_data); MessageType msg; int status = msg.decode(rbuf->data, 0, rbuf->data_size); if (status < 0) { fprintf (stderr, "error %d decoding %s!!!\n", status, MessageType::getTypeName()); return; } const ReceiveBuffer rb = { rbuf->data, rbuf->data_size, rbuf->recv_utime }; std::string chan_str(channel); (subs->handler->*subs->handlerMethod)(&rb, chan_str, &msg); } }; template class LCMMHUntypedSubscription : public Subscription { friend class LCM; private: MessageHandlerClass* handler; void (MessageHandlerClass::*handlerMethod)(const ReceiveBuffer* rbuf, const std::string& channel); static void cb_func(const lcm_recv_buf_t *rbuf, const char *channel, void *user_data) { LCMMHUntypedSubscription *subs = static_cast *>(user_data); const ReceiveBuffer rb = { rbuf->data, rbuf->data_size, rbuf->recv_utime }; std::string chan_str(channel); (subs->handler->*subs->handlerMethod)(&rb, chan_str); } }; inline LCM::LCM(std::string lcm_url): owns_lcm(true) { this->lcm = lcm_create(lcm_url.c_str()); } inline LCM::LCM(lcm_t * lcm_in): owns_lcm(false) { this->lcm = lcm_in; } inline bool LCM::good() const { return this->lcm != NULL; } inline LCM::~LCM() { for(int i=0, n=subscriptions.size(); ilcm && this->owns_lcm) { lcm_destroy(this->lcm); } } inline int LCM::publish(const std::string& channel, const void *data, unsigned int datalen) { if(!this->lcm) { fprintf(stderr, "LCM instance not initialized. Ignoring call to publish()\n"); return -1; } return lcm_publish(this->lcm, channel.c_str(), data, datalen); } template inline int LCM::publish(const std::string& channel, const MessageType *msg) { unsigned int datalen = msg->getEncodedSize(); uint8_t *buf = new uint8_t[datalen]; msg->encode(buf, 0, datalen); int status = this->publish(channel, buf, datalen); delete[] buf; return status; } inline int LCM::unsubscribe(Subscription *subscription) { if(!this->lcm) { fprintf(stderr, "LCM instance not initialized. Ignoring call to unsubscribe()\n"); return -1; } std::vector::iterator iter; std::vector::iterator eiter = subscriptions.end(); for(iter=subscriptions.begin(); iter!= eiter; ++iter) { if(*iter == subscription) { int status = lcm_unsubscribe(lcm, subscription->c_subs); subscriptions.erase(iter); delete subscription; return status; } } return -1; } inline int LCM::getFileno() { if(!this->lcm) { fprintf(stderr, "LCM instance not initialized. Ignoring call to fileno()\n"); return -1; } return lcm_get_fileno(this->lcm); } inline int LCM::handle() { if(!this->lcm) { fprintf(stderr, "LCM instance not initialized. Ignoring call to handle()\n"); return -1; } return lcm_handle(this->lcm); } inline int LCM::handleTimeout(int timeout_millis) { if(!this->lcm) { fprintf(stderr, "LCM instance not initialized. Ignoring call to handle()\n"); return -1; } return lcm_handle_timeout(this->lcm, timeout_millis); } template Subscription* LCM::subscribe(const std::string& channel, void (MessageHandlerClass::*handlerMethod)(const ReceiveBuffer* rbuf, const std::string& channel, const MessageType* msg), MessageHandlerClass* handler) { if(!this->lcm) { fprintf(stderr, "LCM instance not initialized. Ignoring call to subscribe()\n"); return NULL; } LCMMHSubscription *subs = new LCMMHSubscription(); subs->handler = handler; subs->handlerMethod = handlerMethod; subs->c_subs = lcm_subscribe(this->lcm, channel.c_str(), LCMMHSubscription::cb_func, subs); subscriptions.push_back(subs); return subs; } template Subscription* LCM::subscribe(const std::string& channel, void (MessageHandlerClass::*handlerMethod)(const ReceiveBuffer* rbuf, const std::string& channel), MessageHandlerClass* handler) { if(!this->lcm) { fprintf(stderr, "LCM instance not initialized. Ignoring call to subscribe()\n"); return NULL; } LCMMHUntypedSubscription *subs = new LCMMHUntypedSubscription(); subs->handler = handler; subs->handlerMethod = handlerMethod; subs->c_subs = lcm_subscribe(this->lcm, channel.c_str(), LCMMHUntypedSubscription::cb_func, subs); subscriptions.push_back(subs); return subs; } template Subscription* LCM::subscribeFunction(const std::string& channel, void (*handler)(const ReceiveBuffer *rbuf, const std::string& channel, const MessageType *msg, ContextClass context), ContextClass context) { if(!this->lcm) { fprintf(stderr, "LCM instance not initialized. Ignoring call to subscribeFunction()\n"); return NULL; } typedef LCMTypedSubscription SubsClass; SubsClass *sub = new SubsClass(); sub->c_subs = lcm_subscribe(lcm, channel.c_str(), SubsClass::cb_func, sub); sub->handler = handler; sub->context = context; subscriptions.push_back(sub); return sub; } template Subscription* LCM::subscribeFunction(const std::string& channel, void (*handler)(const ReceiveBuffer *rbuf, const std::string& channel, ContextClass context), ContextClass context) { if(!this->lcm) { fprintf(stderr, "LCM instance not initialized. Ignoring call to subscribeFunction()\n"); return NULL; } typedef LCMUntypedSubscription SubsClass; SubsClass *sub = new SubsClass(); sub->c_subs = lcm_subscribe(lcm, channel.c_str(), SubsClass::cb_func, sub); sub->handler = handler; sub->context = context; subscriptions.push_back(sub); return sub; } lcm_t* LCM::getUnderlyingLCM() { return this->lcm; } LogFile::LogFile(const std::string & path, const std::string & mode) : eventlog(lcm_eventlog_create(path.c_str(), mode.c_str())), last_event(NULL) { } LogFile::~LogFile() { if(eventlog) lcm_eventlog_destroy(eventlog); eventlog = NULL; if(last_event) lcm_eventlog_free_event(last_event); last_event = NULL; } bool LogFile::good() const { return eventlog != NULL; } const LogEvent* LogFile::readNextEvent() { lcm_eventlog_event_t* evt = lcm_eventlog_read_next_event(eventlog); if(last_event) lcm_eventlog_free_event(last_event); last_event = evt; if(!evt) return NULL; curEvent.eventnum = evt->eventnum; curEvent.timestamp = evt->timestamp; curEvent.channel.assign(evt->channel, evt->channellen); curEvent.datalen = evt->datalen; curEvent.data = evt->data; return &curEvent; } int LogFile::seekToTimestamp(int64_t timestamp) { return lcm_eventlog_seek_to_timestamp(eventlog, timestamp); } int LogFile::writeEvent(LogEvent* event) { lcm_eventlog_event_t evt; evt.eventnum = event->eventnum; evt.timestamp = event->timestamp; evt.channellen = event->channel.size(); evt.datalen = event->datalen; evt.channel = (char*) event->channel.c_str(); evt.data = event->data; return lcm_eventlog_write_event(eventlog, &evt); } FILE* LogFile::getFilePtr() { return eventlog->f; }