Fawkes API Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * fuse_transfer_widget.cpp - Fuse transfer widget 00004 * 00005 * Created: Wed Mar 19 17:25:10 2008 00006 * Copyright 2008 Daniel Beck 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * This program is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU Library General Public License for more details. 00019 * 00020 * Read the full text in the LICENSE.GPL file in the doc directory. 00021 */ 00022 00023 #include <tools/firestation/fuse_transfer_widget.h> 00024 #include <tools/firestation/colormap_viewer_widget.h> 00025 00026 #include <fvutils/net/fuse_client.h> 00027 #include <fvutils/net/fuse_message.h> 00028 #include <fvutils/net/fuse_lut_content.h> 00029 #include <fvutils/net/fuse_lutlist_content.h> 00030 00031 #include <models/color/lookuptable.h> 00032 00033 #include <netinet/in.h> 00034 #include <cstring> 00035 00036 using namespace fawkes; 00037 using namespace firevision; 00038 00039 /** @class FuseTransferWidget "fuse_transfer_widget.h" 00040 * This class implements the logic for a GUI that allows to transfer LUTs via FUSE. 00041 * 00042 * @author Daniel Beck 00043 */ 00044 00045 /** Constructor. */ 00046 FuseTransferWidget::FuseTransferWidget() 00047 { 00048 m_local_colormap_viewer = new ColormapViewerWidget(); 00049 m_remote_colormap_viewer = new ColormapViewerWidget(); 00050 00051 m_local_lut_list = Gtk::ListStore::create(m_lut_record); 00052 m_remote_lut_list = Gtk::ListStore::create(m_lut_record); 00053 00054 m_signal_update_local_lut_list.connect( sigc::mem_fun( *this, &FuseTransferWidget::update_local_lut_list) ); 00055 m_signal_update_remote_lut_list.connect( sigc::mem_fun( *this, &FuseTransferWidget::update_remote_lut_list) ); 00056 m_signal_get_lut_list.connect( sigc::mem_fun( *this, &FuseTransferWidget::get_lut_list) ); 00057 m_signal_delete_client.connect( sigc::mem_fun( *this, &FuseTransferWidget::delete_clients) ); 00058 m_signal_update_remote_lut.connect( sigc::mem_fun( *this, &FuseTransferWidget::update_remote_lut) ); 00059 00060 m_new_clients.clear(); 00061 m_delete_clients.clear(); 00062 00063 m_cur_client.active = false; 00064 00065 m_btn_upload = 0; 00066 m_btn_download = 0; 00067 m_img_local = 0; 00068 m_img_remote = 0; 00069 m_trv_local_lut_list = 0; 00070 m_trv_remote_lut_list = 0; 00071 } 00072 00073 /** Destructor. */ 00074 FuseTransferWidget::~FuseTransferWidget() 00075 { 00076 delete m_local_colormap_viewer; 00077 delete m_remote_colormap_viewer; 00078 00079 FuseClient* c; 00080 m_new_clients.lock(); 00081 while (m_new_clients.size() != 0) 00082 { 00083 c = m_new_clients.front().client; 00084 m_new_clients.pop(); 00085 c->disconnect(); 00086 c->cancel(); 00087 c->join(); 00088 delete c; 00089 } 00090 m_new_clients.unlock(); 00091 00092 if (m_cur_client.active) 00093 { 00094 m_cur_client.active = false; 00095 m_delete_clients.push_locked(m_cur_client.client); 00096 delete_clients(); 00097 } 00098 } 00099 00100 /** Tell the widget that a new FUSE service has been discovered. 00101 * The widget will then attempt to connect to the host and list the available LUTs. 00102 * @param name the name of the service 00103 * @param host_name the name of the host the service is running on 00104 * @param port the port 00105 */ 00106 void 00107 FuseTransferWidget::add_fountain_service( const char* name, 00108 const char* host_name, 00109 uint16_t port ) 00110 { 00111 ClientData data; 00112 data.client = 0; 00113 data.service_name = std::string(name); 00114 data.host_name = std::string(host_name); 00115 data.port = port; 00116 data.active = false; 00117 00118 m_new_clients.push_locked(data); 00119 m_signal_get_lut_list(); 00120 } 00121 00122 /** Tell the widget that a service is not available any more. 00123 * All entries in the list of remote LUTs for the corresponding service will be deleted. 00124 * @param name the name of the service 00125 */ 00126 void 00127 FuseTransferWidget::remove_fountain_service(const char* name) 00128 { 00129 Gtk::TreeModel::Children children = m_remote_lut_list->children(); 00130 Gtk::TreeModel::Children::iterator iter = children.begin(); 00131 while( iter != children.end() ) 00132 { 00133 Gtk::TreeModel::Row row = *iter; 00134 if (row[m_lut_record.service_name] == Glib::ustring(name)) 00135 { 00136 iter = m_local_lut_list->erase(iter); 00137 m_local_lut_list->row_deleted( m_local_lut_list->get_path(iter) ); 00138 } 00139 else 00140 { 00141 ++iter; 00142 } 00143 } 00144 } 00145 00146 /** Set the current colormap. 00147 * The current colormap is the local colormap that is currently trained. 00148 * @param colormap the colormap 00149 */ 00150 void 00151 FuseTransferWidget::set_current_colormap(YuvColormap* colormap) 00152 { 00153 m_current_colormap = colormap; 00154 00155 // delete existing "Current" row 00156 Gtk::TreeModel::Children children = m_local_lut_list->children(); 00157 Gtk::TreeModel::Children::iterator iter = children.begin(); 00158 while ( iter != children.end() ) 00159 { 00160 Gtk::TreeModel::Row row = *iter; 00161 if (row[m_lut_record.filename] == "Current") 00162 { 00163 iter = m_local_lut_list->erase(iter); 00164 m_local_lut_list->row_deleted( m_local_lut_list->get_path(iter) ); 00165 } 00166 else 00167 { 00168 ++iter; 00169 } 00170 } 00171 00172 Gtk::TreeModel::Row row = *m_local_lut_list->prepend(); 00173 row[m_lut_record.filename] = "Current"; 00174 row[m_lut_record.width] = colormap->width(); 00175 row[m_lut_record.height] = colormap->height(); 00176 row[m_lut_record.depth] = colormap->depth(); 00177 } 00178 00179 void 00180 FuseTransferWidget::update_local_lut_list() 00181 { 00182 if (m_trv_local_lut_list) 00183 { m_trv_local_lut_list->queue_draw(); } 00184 } 00185 00186 void 00187 FuseTransferWidget::update_remote_lut_list() 00188 { 00189 if (m_trv_remote_lut_list) 00190 { m_trv_remote_lut_list->queue_draw(); } 00191 } 00192 00193 /** Set the button to trigger the LUT upload. 00194 * @param btn the upload button 00195 */ 00196 void 00197 FuseTransferWidget::set_upload_btn(Gtk::Button* btn) 00198 { 00199 m_btn_upload = btn; 00200 m_btn_upload->signal_clicked().connect( sigc::mem_fun( *this, &FuseTransferWidget::upload_lut) ); 00201 } 00202 00203 /** Set the button to trigger the LUT download. 00204 * @param btn the download button 00205 */ 00206 void 00207 FuseTransferWidget::set_download_btn(Gtk::Button* btn) 00208 { 00209 m_btn_download = btn; 00210 } 00211 00212 /** Set the Image to display the local LUT. 00213 * @param img the local LUT image 00214 */ 00215 void 00216 FuseTransferWidget::set_local_img(Gtk::Image* img) 00217 { 00218 m_img_local = img; 00219 m_local_colormap_viewer->set_colormap_img(m_img_local); 00220 } 00221 00222 /** Assign a Scale to switch between the layers of the loal colormap. 00223 * @param scl a Gtk::Scale 00224 */ 00225 void 00226 FuseTransferWidget::set_local_layer_selector(Gtk::Scale* scl) 00227 { 00228 m_local_colormap_viewer->set_layer_selector(scl); 00229 } 00230 00231 /** Set the Image to display the remote LUT. 00232 * @param img the remote LUT Image 00233 */ 00234 void 00235 FuseTransferWidget::set_remote_img(Gtk::Image* img) 00236 { 00237 m_img_remote = img; 00238 m_remote_colormap_viewer->set_colormap_img(m_img_remote); 00239 } 00240 00241 /** Assign a Scale to switch between the layers of the remote colormap. 00242 * @param scl a Gtk::Scale 00243 */ 00244 void 00245 FuseTransferWidget::set_remote_layer_selector(Gtk::Scale* scl) 00246 { 00247 m_remote_colormap_viewer->set_layer_selector(scl); 00248 } 00249 00250 /** Set the TreeView for the list of local LUTs. 00251 * @param trv the TreeView for the list of local LUTs 00252 */ 00253 void 00254 FuseTransferWidget::set_local_lut_list_trv(Gtk::TreeView* trv) 00255 { 00256 m_trv_local_lut_list = trv; 00257 m_trv_local_lut_list->set_model(m_local_lut_list); 00258 m_trv_local_lut_list->append_column("Filename", m_lut_record.filename); 00259 m_trv_local_lut_list->append_column("Width", m_lut_record.width); 00260 m_trv_local_lut_list->append_column("Height", m_lut_record.height); 00261 m_trv_local_lut_list->append_column("Depth", m_lut_record.depth); 00262 // m_trv_local_lut_list->append_column("BPC", m_lut_record.bytes_per_cell); 00263 00264 m_trv_local_lut_list->signal_cursor_changed().connect( sigc::mem_fun( *this, &FuseTransferWidget::local_lut_selected) ); 00265 } 00266 00267 /** Set the TreeView for the list of remote LUTs. 00268 * @param trv the TreeView for the list of remote LUTs 00269 */ 00270 void 00271 FuseTransferWidget::set_remote_lut_list_trv(Gtk::TreeView* trv) 00272 { 00273 m_trv_remote_lut_list = trv; 00274 m_trv_remote_lut_list->set_model(m_remote_lut_list); 00275 m_trv_remote_lut_list->append_column("Host", m_lut_record.host_name); 00276 // m_trv_remote_lut_list->append_column("Port", m_lut_record.port); 00277 m_trv_remote_lut_list->append_column("ID", m_lut_record.lut_id); 00278 m_trv_remote_lut_list->append_column("Width", m_lut_record.width); 00279 m_trv_remote_lut_list->append_column("Height", m_lut_record.height); 00280 m_trv_remote_lut_list->append_column("Depth", m_lut_record.depth); 00281 m_trv_remote_lut_list->append_column("BPC", m_lut_record.bytes_per_cell); 00282 00283 m_trv_remote_lut_list->signal_cursor_changed().connect( sigc::mem_fun( *this, &FuseTransferWidget::remote_lut_selected) ); 00284 } 00285 00286 void 00287 FuseTransferWidget::get_lut_list() 00288 { 00289 if (m_cur_client.active) 00290 // communication in progress 00291 { return; } 00292 00293 m_new_clients.lock(); 00294 if (m_new_clients.size() == 0) 00295 { 00296 m_new_clients.unlock(); 00297 return; 00298 } 00299 00300 m_cur_client = m_new_clients.front(); 00301 m_cur_client.active = true; 00302 m_new_clients.pop(); 00303 m_new_clients.unlock(); 00304 00305 try 00306 { 00307 m_cur_client.client = new FuseClient( m_cur_client.host_name.c_str(), 00308 m_cur_client.port, this ); 00309 m_cur_client.client->connect(); 00310 m_cur_client.client->start(); 00311 m_cur_client.client->enqueue(FUSE_MT_GET_LUT_LIST); 00312 } 00313 catch (Exception& e) 00314 { 00315 e.print_trace(); 00316 m_cur_client.client->cancel(); 00317 m_cur_client.client->join(); 00318 delete m_cur_client.client; 00319 m_cur_client.active = false; 00320 } 00321 } 00322 00323 void 00324 FuseTransferWidget::delete_clients() 00325 { 00326 FuseClient* c; 00327 00328 m_delete_clients.lock(); 00329 while (m_delete_clients.size() != 0) 00330 { 00331 c = m_delete_clients.front(); 00332 m_delete_clients.pop(); 00333 00334 c->disconnect(); 00335 c->cancel(); 00336 c->join(); 00337 delete c; 00338 } 00339 m_delete_clients.unlock(); 00340 } 00341 00342 void 00343 FuseTransferWidget::update_local_lut() 00344 { 00345 if ( !m_img_local ) 00346 { return; } 00347 00348 m_local_colormap_viewer->draw(); 00349 } 00350 00351 void 00352 FuseTransferWidget::update_remote_lut() 00353 { 00354 if ( !m_img_remote ) 00355 { return; } 00356 00357 m_remote_colormap_viewer->draw(); 00358 } 00359 00360 void 00361 FuseTransferWidget::upload_lut() 00362 { 00363 if ( !m_local_colormap ) 00364 { return; } 00365 00366 // get current selection remote 00367 Glib::RefPtr<Gtk::TreeSelection> selection = m_trv_remote_lut_list->get_selection(); 00368 00369 if ( 1 != selection->count_selected_rows() ) 00370 { 00371 printf("No remote lut selected\n"); 00372 return; 00373 } 00374 00375 Gtk::TreeModel::iterator i = selection->get_selected(); 00376 Glib::ustring hostname = (*i)[m_lut_record.host_name]; 00377 unsigned int port = (*i)[m_lut_record.port]; 00378 Glib::ustring lut_id = (*i)[m_lut_record.lut_id]; 00379 00380 printf("sending lut to %s:%d id %s\n", hostname.c_str(), port, lut_id.c_str()); 00381 00382 FuseLutContent* lut_content = new FuseLutContent( lut_id.c_str(), 00383 m_local_colormap->get_buffer(), 00384 m_local_colormap->width(), 00385 m_local_colormap->height(), 00386 m_local_colormap->depth(), 00387 1 /* bytes per cell*/ ); 00388 00389 // create FUSE client 00390 FuseClient* client = new FuseClient(hostname.c_str(), port, this); 00391 00392 try 00393 { 00394 client->connect(); 00395 client->start(); 00396 00397 // send lut 00398 client->enqueue( new FuseNetworkMessage(FUSE_MT_SET_LUT, lut_content) ); 00399 00400 // mark FUSE client for deletion 00401 m_delete_clients.push_locked(client); 00402 } 00403 catch (Exception& e) 00404 { 00405 e.print_trace(); 00406 client->cancel(); 00407 client->join(); 00408 delete client; 00409 } 00410 } 00411 00412 void 00413 FuseTransferWidget::local_lut_selected() 00414 { 00415 Glib::RefPtr<Gtk::TreeSelection> selection = m_trv_local_lut_list->get_selection(); 00416 if (selection->count_selected_rows() != 1) 00417 { return; } 00418 00419 Gtk::TreeModel::iterator it = selection->get_selected(); 00420 Glib::ustring filename = (*it)[m_lut_record.filename]; 00421 00422 if (filename == "Current") 00423 { 00424 m_local_colormap = m_current_colormap; 00425 } 00426 else 00427 { 00428 // TODO 00429 } 00430 00431 m_local_colormap_viewer->set_colormap(m_local_colormap); 00432 update_local_lut(); 00433 } 00434 00435 void 00436 FuseTransferWidget::remote_lut_selected() 00437 { 00438 Glib::RefPtr<Gtk::TreeSelection> selection = m_trv_remote_lut_list->get_selection(); 00439 if (selection->count_selected_rows() != 1) 00440 { return; } 00441 00442 Gtk::TreeModel::iterator it = selection->get_selected(); 00443 Glib::ustring host_name = (*it)[m_lut_record.host_name]; 00444 unsigned int port = (*it)[m_lut_record.port]; 00445 Glib::ustring lut_id = (*it)[m_lut_record.lut_id]; 00446 00447 FuseClient* c = new FuseClient(host_name.c_str(), port, this); 00448 try 00449 { 00450 c->connect(); 00451 c->start(); 00452 00453 FUSE_lutdesc_message_t* lut_desc = (FUSE_lutdesc_message_t*) malloc( sizeof(FUSE_lutdesc_message_t)); 00454 memset(lut_desc, 0, sizeof(FUSE_lutdesc_message_t)); 00455 strncpy(lut_desc->lut_id, lut_id.c_str(), LUT_ID_MAX_LENGTH); 00456 c->enqueue(FUSE_MT_GET_LUT, lut_desc, sizeof(FUSE_lutdesc_message_t)); 00457 00458 m_delete_clients.push_locked(c); 00459 } 00460 catch (Exception& e) 00461 { 00462 e.print_trace(); 00463 c->cancel(); 00464 c->join(); 00465 delete c; 00466 } 00467 } 00468 00469 void 00470 FuseTransferWidget::fuse_invalid_server_version(uint32_t local_version, 00471 uint32_t remote_version) throw() 00472 { 00473 printf("Invalid versions: local: %u remote: %u\n", local_version, remote_version); 00474 } 00475 00476 void 00477 FuseTransferWidget::fuse_connection_established () throw() 00478 { 00479 } 00480 00481 void 00482 FuseTransferWidget::fuse_connection_died() throw() 00483 { 00484 if (m_cur_client.active) 00485 { 00486 m_delete_clients.push_locked(m_cur_client.client); 00487 m_cur_client.active = false; 00488 } 00489 00490 m_signal_delete_client(); 00491 } 00492 00493 void 00494 FuseTransferWidget::fuse_inbound_received (FuseNetworkMessage *m) throw() 00495 { 00496 switch ( m->type() ) 00497 { 00498 case FUSE_MT_LUT_LIST: 00499 try 00500 { 00501 FuseLutListContent* content = m->msgc<FuseLutListContent>(); 00502 if ( content->has_next() ) 00503 { 00504 while ( content->has_next() ) 00505 { 00506 // check whether there already is an entry for the given lut_id 00507 FUSE_lutinfo_t* lut_info = content->next(); 00508 char lut_id[LUT_ID_MAX_LENGTH + 1]; 00509 lut_id[LUT_ID_MAX_LENGTH] = '\0'; 00510 strncpy(lut_id, lut_info->lut_id, LUT_ID_MAX_LENGTH); 00511 00512 Gtk::TreeModel::Children children = m_remote_lut_list->children(); 00513 Gtk::TreeModel::Children::iterator iter = children.begin(); 00514 while ( iter != children.end() ) 00515 { 00516 Gtk::TreeModel::Row row = *iter; 00517 if ( row[m_lut_record.lut_id] == Glib::ustring(lut_id) ) 00518 { iter = m_remote_lut_list->erase(iter); } 00519 else 00520 { ++iter; } 00521 } 00522 00523 Gtk::TreeModel::Row row = *m_remote_lut_list->append(); 00524 row[m_lut_record.service_name] = Glib::ustring(m_cur_client.service_name); 00525 row[m_lut_record.host_name] = Glib::ustring(m_cur_client.host_name); 00526 row[m_lut_record.port] = m_cur_client.port; 00527 row[m_lut_record.lut_id] = Glib::ustring(lut_id); 00528 row[m_lut_record.width] = ntohl(lut_info->width); 00529 row[m_lut_record.height] = ntohl(lut_info->height); 00530 row[m_lut_record.depth] = ntohl(lut_info->depth); 00531 row[m_lut_record.bytes_per_cell] = ntohl(lut_info->bytes_per_cell); 00532 } 00533 } 00534 delete content; 00535 } 00536 catch (Exception& e) 00537 { 00538 e.print_trace(); 00539 } 00540 00541 m_delete_clients.push_locked(m_cur_client.client); 00542 m_cur_client.active = false; 00543 00544 m_signal_update_remote_lut_list(); 00545 m_signal_get_lut_list(); 00546 m_signal_delete_client(); 00547 00548 break; 00549 00550 case FUSE_MT_LUT: 00551 try 00552 { 00553 FuseLutContent* lut_content = m->msgc<FuseLutContent>(); 00554 00555 if (m_remote_colormap) 00556 { delete m_remote_colormap; } 00557 00558 if ( lut_content->width() != 256 || 00559 lut_content->height() != 256 ) 00560 { 00561 m_signal_delete_client(); 00562 break; 00563 } 00564 00565 m_remote_colormap = new YuvColormap( lut_content->depth() ); 00566 m_remote_colormap->set( lut_content->buffer() ); 00567 00568 delete lut_content; 00569 } 00570 catch (Exception& e) 00571 { 00572 e.print_trace(); 00573 } 00574 m_remote_colormap_viewer->set_colormap(m_remote_colormap); 00575 m_signal_update_remote_lut(); 00576 m_signal_delete_client(); 00577 00578 break; 00579 00580 case FUSE_MT_SET_LUT_FAILED: 00581 printf("LUT upload failed\n"); 00582 00583 case FUSE_MT_SET_LUT_SUCCEEDED: 00584 printf("LUT upload succeeded\n"); 00585 m_signal_delete_client(); 00586 break; 00587 00588 default: 00589 printf("Unhandled message type\n"); 00590 } 00591 }