fuse_transfer_widget.cpp

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 }

Generated on 1 Mar 2011 for Fawkes API by  doxygen 1.6.1