00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "fuse_image_list_widget.h"
00024
00025 #include <fvutils/net/fuse_message.h>
00026 #include <fvutils/net/fuse_imagelist_content.h>
00027
00028 #include <netinet/in.h>
00029 #include <cstring>
00030 #include <sstream>
00031
00032 using namespace fawkes;
00033
00034 namespace firevision {
00035 #if 0
00036 }
00037 #endif
00038
00039
00040
00041
00042
00043
00044
00045
00046 FuseImageListWidget::FuseImageListWidget()
00047 {
00048 m_chk_compression = NULL;
00049 m_chk_auto_update = NULL;
00050
00051 m_cur_client.active = false;
00052
00053 m_new_clients.clear();
00054 m_delete_clients.clear();
00055
00056 m_image_list = Gtk::TreeStore::create(m_image_record);
00057
00058 m_signal_get_image_list.connect( sigc::mem_fun( *this, &FuseImageListWidget::get_image_list) );
00059 m_signal_delete_clients.connect( sigc::mem_fun( *this, &FuseImageListWidget::delete_clients) );
00060 m_signal_update_image_l.connect( sigc::mem_fun( *this, &FuseImageListWidget::update_image_list) );
00061
00062 m_popup_menu = Gtk::manage( new Gtk::Menu() );
00063 Gtk::Menu::MenuList& menulist = m_popup_menu->items();
00064 menulist.push_back( Gtk::Menu_Helpers::MenuElem("Update now", sigc::mem_fun( *this, &FuseImageListWidget::update_image_list) ) );
00065 menulist.push_back( Gtk::Menu_Helpers::SeparatorElem() );
00066 menulist.push_back( Gtk::Menu_Helpers::MenuElem("Add host manually", sigc::mem_fun( *this, &FuseImageListWidget::on_add_host_manually) ) );
00067
00068 set_image_list_trv(this);
00069 }
00070
00071
00072 FuseImageListWidget::~FuseImageListWidget()
00073 {
00074 FuseClient* c;
00075 m_new_clients.lock();
00076 while (m_new_clients.size() != 0)
00077 {
00078 c = m_new_clients.front().client;
00079 m_new_clients.pop_front();
00080 c->disconnect();
00081 c->cancel();
00082 c->join();
00083 delete c;
00084 }
00085 m_new_clients.unlock();
00086
00087 if (m_cur_client.active)
00088 {
00089 m_cur_client.active = false;
00090 m_delete_clients.push_locked(m_cur_client.client);
00091 }
00092 delete_clients();
00093 }
00094
00095
00096
00097
00098
00099
00100 void
00101 FuseImageListWidget::add_fountain_service( const char* name,
00102 const char* host_name,
00103 uint32_t port )
00104 {
00105
00106 m_img_list_mutex.lock();
00107 Gtk::TreeModel::Children children = m_image_list->children();
00108 for ( Gtk::TreeModel::Children::iterator iter = children.begin();
00109 iter != children.end(); ++iter )
00110 {
00111 Gtk::TreeModel::Row row = *iter;
00112 if ( row[m_image_record.service_name] == Glib::ustring(name) )
00113 {
00114 m_img_list_mutex.unlock();
00115 return;
00116 }
00117 }
00118 m_img_list_mutex.unlock();
00119
00120
00121 m_new_clients.lock();
00122 for ( LockList<ClientData>::iterator iter = m_new_clients.begin();
00123 iter != m_new_clients.end(); ++iter )
00124 {
00125 if (name == iter->service_name)
00126 {
00127 m_new_clients.unlock();
00128 return;
00129 }
00130 }
00131 m_new_clients.unlock();
00132
00133 ClientData data;
00134 data.client = 0;
00135 data.service_name = std::string(name);
00136 data.host_name = std::string(host_name);
00137 data.port = port;
00138 data.active = false;
00139
00140 m_new_clients.push_back_locked(data);
00141 m_signal_get_image_list();
00142 }
00143
00144
00145
00146
00147 void
00148 FuseImageListWidget::remove_fountain_service(const char* name)
00149 {
00150 m_img_list_mutex.lock();
00151 Gtk::TreeModel::Children children = m_image_list->children();
00152 Gtk::TreeModel::Children::iterator iter = children.begin();
00153 while ( iter != children.end() )
00154 {
00155 Gtk::TreeModel::Row row = *iter;
00156 if ( row[m_image_record.service_name] == Glib::ustring(name) )
00157 {
00158 iter = m_image_list->erase(iter);
00159 m_image_list->row_deleted( m_image_list->get_path(iter) );
00160 }
00161 else
00162 {
00163 ++iter;
00164 }
00165 }
00166 m_img_list_mutex.unlock();
00167 }
00168
00169
00170
00171
00172 void
00173 FuseImageListWidget::set_image_list_trv(Gtk::TreeView* trv)
00174 {
00175 m_img_list_mutex.lock();
00176 m_trv_image_list = trv;
00177 m_trv_image_list->set_model(m_image_list);
00178 m_trv_image_list->append_column("asdf", m_image_record.display_text);
00179 m_trv_image_list->set_headers_visible(false);
00180 m_trv_image_list->signal_event().connect( sigc::mem_fun(*this, &FuseImageListWidget::on_image_event) );
00181 m_trv_image_list->signal_cursor_changed().connect( sigc::mem_fun(*this, &FuseImageListWidget::on_image_selected) );
00182 m_img_list_mutex.unlock();
00183 }
00184
00185
00186
00187
00188 void
00189 FuseImageListWidget::set_toggle_compression_chk(Gtk::CheckButton* chk)
00190 {
00191 m_chk_compression = chk;
00192 m_chk_compression->signal_toggled().connect( sigc::mem_fun(*this, &FuseImageListWidget::on_compression_toggled) );
00193 }
00194
00195
00196
00197
00198 void
00199 FuseImageListWidget::set_auto_update_chk(Gtk::CheckButton* chk)
00200 {
00201 m_chk_auto_update = chk;
00202 m_chk_auto_update->signal_toggled().connect( sigc::mem_fun(*this, &FuseImageListWidget::on_auto_update_toggled) );
00203 }
00204
00205
00206
00207
00208
00209
00210 Glib::Dispatcher&
00211 FuseImageListWidget::image_selected()
00212 {
00213 return m_signal_image_selected;
00214 }
00215
00216
00217
00218
00219 bool
00220 FuseImageListWidget::auto_update()
00221 {
00222 return m_auto_update;
00223 }
00224
00225
00226
00227
00228
00229 void
00230 FuseImageListWidget::set_auto_update(bool active, unsigned int interval_sec)
00231 {
00232 m_auto_update = active;
00233 m_interval_sec = interval_sec;
00234
00235 if (m_auto_update)
00236 {
00237 #if GLIBMM_MAJOR_VERSION > 2 || ( GLIBMM_MAJOR_VERSION == 2 && GLIBMM_MINOR_VERSION >= 14 )
00238 m_timeout_conn = Glib::signal_timeout().connect_seconds( sigc::mem_fun(*this, &FuseImageListWidget::on_update_timeout),
00239 m_interval_sec);
00240 #else
00241 m_timeout_conn = Glib::signal_timeout().connect(sigc::mem_fun(*this, &FuseImageListWidget::on_update_timeout), m_interval_sec);
00242 #endif
00243 }
00244 else m_timeout_conn.disconnect();
00245 }
00246
00247
00248
00249
00250
00251
00252
00253
00254 bool
00255 FuseImageListWidget::get_selected_image( std::string& host_name, unsigned short& port,
00256 std::string& image_id, bool& compression )
00257 {
00258 if ( !m_trv_image_list )
00259 { return false; }
00260
00261 m_img_list_mutex.lock();
00262 Glib::RefPtr<Gtk::TreeSelection> selection = m_trv_image_list->get_selection();
00263
00264 if ( selection->count_selected_rows() != 1 )
00265 {
00266 m_img_list_mutex.unlock();
00267 return false;
00268 }
00269
00270 Gtk::TreeModel::iterator iter = selection->get_selected();
00271 host_name = iter->get_value(m_image_record.host_name);
00272 port = iter->get_value(m_image_record.port);
00273 image_id = iter->get_value(m_image_record.image_id);
00274 m_img_list_mutex.unlock();
00275
00276 if (m_chk_compression)
00277 { compression = m_chk_compression->get_active(); }
00278 else
00279 { compression = false; }
00280
00281 return true;
00282 }
00283
00284
00285 bool
00286 FuseImageListWidget::on_image_event(GdkEvent *event)
00287 {
00288 GdkEventButton btn = event->button;
00289 if (btn.type == GDK_BUTTON_PRESS && btn.button == 3) {
00290 m_popup_menu->popup(btn.button, btn.time);
00291 return true;
00292 }
00293 return false;
00294 }
00295
00296 void
00297 FuseImageListWidget::on_image_selected()
00298 {
00299 m_img_list_mutex.lock();
00300 Glib::RefPtr<Gtk::TreeSelection> selection = m_trv_image_list->get_selection();
00301
00302 Gtk::TreeModel::iterator iter = selection->get_selected();
00303 Glib::ustring image_id;
00304 image_id = (*iter)[m_image_record.image_id];
00305 m_img_list_mutex.unlock();
00306
00307 if ((image_id != m_cur_image_id) && (image_id != "invalid"))
00308 {
00309 m_cur_image_id = image_id;
00310 m_signal_image_selected();
00311 }
00312 }
00313
00314 void
00315 FuseImageListWidget::on_auto_update_toggled()
00316 {
00317 set_auto_update( m_chk_auto_update->get_active() );
00318 }
00319
00320 void
00321 FuseImageListWidget::on_compression_toggled()
00322 {
00323 m_signal_image_selected();
00324 }
00325
00326 void
00327 FuseImageListWidget::get_image_list()
00328 {
00329 if (m_cur_client.active)
00330
00331 { return; }
00332
00333 m_new_clients.lock();
00334 if (m_new_clients.size() == 0)
00335 {
00336 if (m_auto_update)
00337 {
00338 #if GLIBMM_MAJOR_VERSION > 2 || ( GLIBMM_MAJOR_VERSION == 2 && GLIBMM_MINOR_VERSION >= 14 )
00339 m_timeout_conn = Glib::signal_timeout().connect_seconds( sigc::mem_fun(*this, &FuseImageListWidget::on_update_timeout),
00340 m_interval_sec);
00341 #else
00342 m_timeout_conn = Glib::signal_timeout().connect(sigc::mem_fun(*this, &FuseImageListWidget::on_update_timeout), m_interval_sec);
00343 #endif
00344 }
00345 m_new_clients.unlock();
00346 return;
00347 }
00348
00349 m_cur_client = m_new_clients.front();
00350 m_cur_client.active = true;
00351 m_new_clients.pop_front();
00352 m_new_clients.unlock();
00353
00354 try
00355 {
00356 m_cur_client.client = new FuseClient( m_cur_client.host_name.c_str(),
00357 m_cur_client.port, this );
00358 m_cur_client.client->connect();
00359 m_cur_client.client->start();
00360 m_cur_client.client->enqueue(FUSE_MT_GET_IMAGE_LIST);
00361 }
00362 catch (Exception& e)
00363 {
00364 e.print_trace();
00365 m_cur_client.client->cancel();
00366 m_cur_client.client->join();
00367 delete m_cur_client.client;
00368 m_cur_client.active = false;
00369 }
00370 }
00371
00372 void
00373 FuseImageListWidget::delete_clients()
00374 {
00375 FuseClient* c = 0;
00376
00377 m_delete_clients.lock();
00378 while (m_delete_clients.size() != 0)
00379 {
00380 c = m_delete_clients.front();
00381 m_delete_clients.pop();
00382
00383 c->disconnect();
00384 c->cancel();
00385 c->join();
00386 delete c;
00387 }
00388 m_delete_clients.unlock();
00389 }
00390
00391 bool
00392 FuseImageListWidget::on_update_timeout()
00393 {
00394 m_signal_update_image_l();
00395 return m_auto_update;
00396 }
00397
00398 void
00399 FuseImageListWidget::update_image_list()
00400 {
00401 m_timeout_conn.disconnect();
00402 if (m_img_list_mutex.try_lock())
00403 {
00404 Gtk::TreeModel::Children children = m_image_list->children();
00405 for ( Gtk::TreeModel::Children::iterator iter = children.begin();
00406 iter != children.end(); ++iter )
00407 {
00408 if ( (*iter)[m_image_record.image_id] == "invalid" )
00409 {
00410 ClientData data;
00411 data.client = 0;
00412 Glib::ustring service_name = (*iter)[m_image_record.service_name];
00413 Glib::ustring host_name = (*iter)[m_image_record.host_name];
00414 data.service_name = std::string( service_name.c_str() );
00415 data.host_name = std::string( host_name.c_str() );
00416 data.port = (*iter)[m_image_record.port];
00417 data.active = false;
00418
00419 m_new_clients.push_back_locked(data);
00420 }
00421 }
00422 m_img_list_mutex.unlock();
00423 }
00424
00425 m_signal_get_image_list();
00426 }
00427
00428 void
00429 FuseImageListWidget::fuse_invalid_server_version(uint32_t local_version,
00430 uint32_t remote_version) throw()
00431 {
00432 printf("Invalid versions: local: %u remote: %u\n", local_version, remote_version);
00433 }
00434
00435 void
00436 FuseImageListWidget::fuse_connection_established () throw()
00437 {
00438 }
00439
00440 void
00441 FuseImageListWidget::fuse_connection_died() throw()
00442 {
00443 if (m_cur_client.active)
00444 {
00445 m_delete_clients.push_locked(m_cur_client.client);
00446 m_cur_client.active = false;
00447 }
00448
00449 m_signal_delete_clients();
00450 }
00451
00452 void
00453 FuseImageListWidget::fuse_inbound_received (FuseNetworkMessage *m) throw()
00454 {
00455 switch ( m->type() )
00456 {
00457 case FUSE_MT_IMAGE_LIST:
00458 {
00459
00460 m_img_list_mutex.lock();
00461 Gtk::TreeModel::Children children = m_image_list->children();
00462 Gtk::TreeModel::Children::iterator iter = children.begin();
00463 while ( iter != children.end() )
00464 {
00465 Gtk::TreeModel::Row row = *iter;
00466 if ( row[m_image_record.service_name] == Glib::ustring(m_cur_client.service_name) )
00467 {
00468 iter = m_image_list->erase(iter);
00469 }
00470 else
00471 {
00472 ++iter;
00473 }
00474 }
00475
00476 try
00477 {
00478 FuseImageListContent* content = m->msgc<FuseImageListContent>();
00479 if ( content->has_next() )
00480 {
00481 Gtk::TreeModel::Row row = *m_image_list->append();
00482 row[m_image_record.display_text] = Glib::ustring(m_cur_client.host_name);
00483 row[m_image_record.service_name] = Glib::ustring(m_cur_client.service_name);
00484 row[m_image_record.host_name] = Glib::ustring(m_cur_client.host_name);
00485 row[m_image_record.port] = m_cur_client.port;
00486 row[m_image_record.colorspace] = 0;
00487 row[m_image_record.image_id] = "invalid";
00488 row[m_image_record.width] = 0;
00489 row[m_image_record.height] = 0;
00490 row[m_image_record.buffer_size] = 0;
00491
00492 Gtk::TreeModel::Path path = m_image_list->get_path(row);
00493
00494 while ( content->has_next() )
00495 {
00496 FUSE_imageinfo_t* image_info = content->next();
00497 char image_id[IMAGE_ID_MAX_LENGTH + 1];
00498 image_id[IMAGE_ID_MAX_LENGTH] = '\0';
00499 strncpy(image_id, image_info->image_id, IMAGE_ID_MAX_LENGTH);
00500
00501 Gtk::TreeModel::Row childrow = *m_image_list->append( row.children() );
00502 childrow[m_image_record.display_text] = Glib::ustring(image_id);
00503 childrow[m_image_record.service_name] = Glib::ustring(m_cur_client.service_name);
00504 childrow[m_image_record.host_name] = Glib::ustring(m_cur_client.host_name);
00505 childrow[m_image_record.port] = m_cur_client.port;
00506 childrow[m_image_record.colorspace] = ntohl(image_info->colorspace);
00507 childrow[m_image_record.image_id] = Glib::ustring(image_id);
00508 childrow[m_image_record.width] = ntohl(image_info->width);
00509 childrow[m_image_record.height] = ntohl(image_info->height);
00510 childrow[m_image_record.buffer_size] = ntohl(image_info->buffer_size);
00511 }
00512
00513 m_trv_image_list->expand_row(path, false);
00514 }
00515
00516 delete content;
00517 }
00518 catch (Exception& e)
00519 {
00520 e.print_trace();
00521 }
00522
00523 m_img_list_mutex.unlock();
00524
00525 m_delete_clients.push_locked(m_cur_client.client);
00526 m_cur_client.active = false;
00527
00528 m_signal_get_image_list();
00529 m_signal_delete_clients();
00530
00531 break;
00532 }
00533
00534 default:
00535 printf("Unhandled message type\n");
00536 }
00537 }
00538
00539 void
00540 FuseImageListWidget::on_add_host_manually()
00541 {
00542 Gtk::Dialog* add_host = new Gtk::Dialog("Add host manually", this->get_window(), true);
00543 add_host->add_button(Gtk::Stock::ADD, Gtk::RESPONSE_OK);
00544 add_host->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
00545
00546 Gtk::Table* tab = Gtk::manage( new Gtk::Table(2, 2, false) );
00547 Gtk::Label* hlab = Gtk::manage( new Gtk::Label("Host:") );
00548 Gtk::Label* plab = Gtk::manage( new Gtk::Label("Port:") );
00549 Gtk::Entry* hent = Gtk::manage( new Gtk::Entry() );
00550 Gtk::HBox* pbox = Gtk::manage( new Gtk::HBox() );
00551
00552 Gtk::Adjustment prange(2208, 1, 65535);
00553 Gtk::SpinButton *pent = Gtk::manage( new Gtk::SpinButton(prange) );
00554
00555 char * fawkes_ip = getenv("FAWKES_IP");
00556 if (fawkes_ip) hent->set_text(std::string(fawkes_ip).append(":2208"));
00557 else hent->set_text("localhost:2208");
00558
00559 pbox->pack_start(*pent, false, false, 0);
00560 tab->attach(*hlab, 1, 2, 1, 2);
00561 tab->attach(*plab, 1, 2, 2, 3);
00562 tab->attach(*hent, 2, 3, 1, 2);
00563 tab->attach(*pbox, 2, 3, 2, 3);
00564
00565 add_host->get_vbox()->pack_start(*tab, false, true, 0);
00566 add_host->get_vbox()->show_all_children(true);
00567
00568 if (add_host->run() == Gtk::RESPONSE_OK) {
00569 std::string name = "fountain on ";
00570 std::string host = hent->get_text();
00571 unsigned short port = 2208;
00572
00573 Glib::ustring::size_type pos;
00574 if ((pos = host.find(':')) != Glib::ustring::npos)
00575 {
00576 Glib::ustring tmp_host = "";
00577 unsigned int tmp_port = 1234567;
00578 std::istringstream is(host.replace(pos, 1, " "));
00579 is >> tmp_host;
00580 is >> tmp_port;
00581
00582 if (tmp_port != 1234567 && tmp_host.size())
00583 {
00584 host = tmp_host;
00585 port = tmp_port;
00586 }
00587 }
00588
00589 name.append(host);
00590 add_fountain_service(name.c_str(), host.c_str(), port);
00591 }
00592
00593 add_host->hide();
00594 delete add_host;
00595 }
00596
00597 }