Fawkes API
Fawkes Development Version
|
00001 /*************************************************************************** 00002 * firestation.cpp - Firestation 00003 * 00004 * Created: Wed Oct 10 14:19:30 2007 00005 * Copyright 2007-2008 Daniel Beck 00006 * 00007 ****************************************************************************/ 00008 00009 /* This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU Library General Public License for more details. 00018 * 00019 * Read the full text in the LICENSE.GPL file in the doc directory. 00020 */ 00021 00022 #include "firestation.h" 00023 #include "color_train_widget.h" 00024 #include "fuse_transfer_widget.h" 00025 00026 #include <utils/math/angle.h> 00027 00028 #include <fvwidgets/fuse_image_list_widget.h> 00029 #include <gui_utils/avahi_dispatcher.h> 00030 00031 #include <fvcams/fileloader.h> 00032 #include <fvcams/shmem.h> 00033 #include <fvcams/net.h> 00034 00035 #ifdef HAVE_MIRROR_CALIB 00036 #include <fvmodels/mirror/mirror_calib.h> 00037 #endif 00038 00039 #include <fvutils/ipc/shm_image.h> 00040 #include <fvutils/color/conversions.h> 00041 #include <fvutils/color/yuv.h> 00042 #include <fvutils/colormap/yuvcm.h> 00043 #include <fvutils/scalers/lossy.h> 00044 #include <fvutils/system/camargp.h> 00045 #include <fvutils/writers/jpeg.h> 00046 #include <fvutils/writers/fvraw.h> 00047 #include <fvutils/draw/drawer.h> 00048 00049 #include <core/exception.h> 00050 00051 #include <gdkmm/pixbuf.h> 00052 00053 #include <arpa/inet.h> 00054 00055 #include <iostream> 00056 00057 using namespace std; 00058 using namespace fawkes; 00059 using namespace firevision; 00060 00061 /** @class Firestation "firestation.h" 00062 * Control GUI for vision related stuff. 00063 * @author Daniel Beck 00064 */ 00065 00066 /** Constructor. 00067 * @param builder Gtk Builder 00068 */ 00069 Firestation::Firestation(Glib::RefPtr<Gtk::Builder> builder) 00070 { 00071 // --- main window ------------------------------------------------ 00072 builder->get_widget("wndMain", m_wnd_main); 00073 builder->get_widget("imgImage", m_img_image); 00074 builder->get_widget("evtImageEventBox", m_evt_image); 00075 builder->get_widget("trvShmImageIds", m_trv_shm_image_ids); 00076 builder->get_widget("stbStatus", m_stb_status); 00077 builder->get_widget("ckbContTrans", m_ckb_cont_trans); 00078 builder->get_widget("spbUpdateTime", m_spb_update_time); 00079 00080 m_img_image->signal_size_allocate().connect( sigc::mem_fun(*this, &Firestation::resize_image) ); 00081 m_evt_image->signal_button_press_event().connect( sigc::mem_fun(*this, &Firestation::image_click) ); 00082 m_ckb_cont_trans->signal_toggled().connect( sigc::mem_fun(*this, &Firestation::enable_cont_img_trans) ); 00083 00084 // ---------------------------------------------------------------- 00085 00086 00087 // --- toolbar widgets -------------------------------------------- 00088 builder->get_widget("tbtnExit", m_tbtn_exit); 00089 builder->get_widget("tbtnCloseCamera", m_tbtn_close_camera); 00090 builder->get_widget("tbtnUpdate", m_tbtn_update); 00091 builder->get_widget("tbtnSave", m_tbtn_save); 00092 builder->get_widget("tbtnOpenFile", m_tbtn_open_file); 00093 builder->get_widget("tbtnOpenFolder", m_tbtn_open_folder); 00094 builder->get_widget("tbtnOpenShm", m_tbtn_open_shm); 00095 builder->get_widget("tbtnOpenFuse", m_tbtn_open_fuse); 00096 00097 m_tbtn_exit->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::exit) ); 00098 m_tbtn_close_camera->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::close_camera) ); 00099 m_tbtn_update->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::update_image) ); 00100 m_tbtn_save->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::save_image) ); 00101 m_tbtn_open_file->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::open_file) ); 00102 m_tbtn_open_folder->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::open_folder) ); 00103 m_tbtn_open_shm->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::open_shm) ); 00104 m_tbtn_open_fuse->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::open_fuse) ); 00105 // ---------------------------------------------------------------- 00106 00107 00108 // --- dialogs ---------------------------------------------------- 00109 builder->get_widget("fcdOpenImage", m_fcd_open_image); 00110 builder->get_widget("fcdSaveImage", m_fcd_save_image); 00111 builder->get_widget("dlgOpenShm", m_dlg_open_shm); 00112 builder->get_widget("trvShmImageIds", m_trv_shm_image_ids); 00113 builder->get_widget("dlgOpenFuse", m_dlg_open_fuse); 00114 builder->get_widget("ckbFuseJpeg", m_ckb_fuse_jpeg); 00115 builder->get_widget("trvFuseServices", m_trv_fuse_services); 00116 00117 #if GTK_VERSION_GE(3,0) 00118 Glib::RefPtr<Gtk::FileFilter> filter_jpg = Gtk::FileFilter::create(); 00119 #else 00120 Gtk::FileFilter *filter_jpg = Gtk::manage(new Gtk::FileFilter()); 00121 #endif 00122 filter_jpg->set_name("JPEG"); 00123 filter_jpg->add_pattern("*.jpg"); 00124 filter_jpg->add_pattern("*.jpeg"); 00125 00126 #if GTK_VERSION_GE(3,0) 00127 Glib::RefPtr<Gtk::FileFilter> filter_fvraw = Gtk::FileFilter::create(); 00128 #else 00129 Gtk::FileFilter *filter_fvraw = Gtk::manage(new Gtk::FileFilter()); 00130 #endif 00131 filter_fvraw->set_name("FVRaw"); 00132 filter_fvraw->add_pattern("*.raw"); 00133 filter_fvraw->add_pattern("*.fvraw"); 00134 00135 #if GTK_VERSION_GE(3,0) 00136 m_fcd_open_image->add_filter(filter_jpg); 00137 m_fcd_open_image->add_filter(filter_fvraw); 00138 00139 m_fcd_save_image->add_filter(filter_jpg); 00140 m_fcd_save_image->add_filter(filter_fvraw); 00141 00142 #else 00143 m_fcd_open_image->add_filter(*filter_jpg); 00144 m_fcd_open_image->add_filter(*filter_fvraw); 00145 00146 m_fcd_save_image->add_filter(*filter_jpg); 00147 m_fcd_save_image->add_filter(*filter_fvraw); 00148 #endif 00149 00150 m_shm_list_store = Gtk::ListStore::create(m_shm_columns); 00151 m_trv_shm_image_ids->set_model(m_shm_list_store); 00152 m_trv_shm_image_ids->append_column("#", m_shm_columns.m_id); 00153 m_trv_shm_image_ids->append_column("Name", m_shm_columns.m_name); 00154 00155 m_fuse_tree_store = Gtk::TreeStore::create(m_fuse_columns); 00156 m_trv_fuse_services->set_model(m_fuse_tree_store); 00157 // m_trv_fuse_services->append_column("#", m_fuse_columns.m_id); 00158 m_trv_fuse_services->append_column("Name", m_fuse_columns.m_name); 00159 // ---------------------------------------------------------------- 00160 00161 00162 // --- color train widget ----------------------------------------- 00163 m_ctw = new ColorTrainWidget(this); 00164 builder->get_widget("cmbCtObjectType", m_cmb_ct_type); 00165 builder->get_widget("btnCtStart", m_btn_ct_start); 00166 builder->get_widget("btnCtSeg", m_btn_ct_seg); 00167 builder->get_widget("spbtnCtCmDepth", m_spbtn_depth); 00168 builder->get_widget("spbtnCtCmWidth", m_spbtn_width); 00169 builder->get_widget("spbtnCtCmHeight", m_spbtn_height); 00170 00171 m_cmb_ct_type->signal_changed().connect(sigc::mem_fun(*this, &Firestation::ct_object_changed)); 00172 m_cmb_ct_type->set_active(0); 00173 00174 m_btn_ct_start->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::ct_start) ); 00175 00176 m_ctw->update_image().connect( sigc::mem_fun(*this, &Firestation::draw_image) ); 00177 m_ctw->colormap_updated().connect( sigc::mem_fun(*this, &Firestation::on_colormap_updated) ); 00178 00179 Gtk::Button* btn; 00180 builder->get_widget("btnCtUnselect", btn); 00181 m_ctw->set_reset_selection_btn(btn); 00182 00183 builder->get_widget("btnCtAdd", btn); 00184 m_ctw->set_add_to_colormap_btn(btn); 00185 00186 builder->get_widget("btnCtReset", btn); 00187 m_ctw->set_reset_colormap_btn(btn); 00188 00189 builder->get_widget("btnCtSaveHistos", btn); 00190 m_ctw->set_save_histos_btn(btn); 00191 00192 builder->get_widget("btnCtLoadHistos", btn); 00193 m_ctw->set_load_histos_btn(btn); 00194 00195 builder->get_widget("btnCtSaveColormap", btn); 00196 m_ctw->set_save_colormap_btn(btn); 00197 00198 builder->get_widget("btnCtLoadColormap", btn); 00199 m_ctw->set_load_colormap_btn(btn); 00200 00201 Gtk::Scale* scl; 00202 builder->get_widget("sclCtThreshold", scl); 00203 m_ctw->set_threshold_scl(scl); 00204 00205 builder->get_widget("sclCtMinProb", scl); 00206 m_ctw->set_min_prob_scl(scl); 00207 00208 builder->get_widget("sclCtLayerSelector", scl); 00209 m_ctw->set_cm_layer_selector(scl); 00210 00211 Gtk::Image* img; 00212 builder->get_widget("imgCtSegmentation", img); 00213 m_ctw->set_segmentation_img(img); 00214 00215 builder->get_widget("imgCtColormap", img); 00216 m_ctw->set_colormap_img(img); 00217 00218 Gtk::FileChooserDialog* fcd; 00219 builder->get_widget("fcdFilechooser", fcd); 00220 m_ctw->set_filechooser_dlg(fcd); 00221 00222 00223 m_btn_ct_seg->signal_toggled().connect( sigc::mem_fun(*this, &Firestation::draw_image) ); 00224 m_ctw->set_cm_selector(m_spbtn_depth, m_spbtn_width, m_spbtn_height); 00225 // ---------------------------------------------------------------- 00226 00227 00228 // --- mirror calibration ----------------------------------------- 00229 #ifdef HAVE_MIRROR_CALIB 00230 m_calib_tool = new firevision::MirrorCalibTool(); 00231 #endif 00232 00233 #ifndef HAVE_MIRROR_CALIB 00234 Gtk::Notebook *nb; 00235 Gtk::HBox *box; 00236 builder->get_widget("ntbOptions", nb); 00237 builder->get_widget("boxMirrorCalib", box); 00238 nb->get_tab_label(*box)->set_sensitive(false); 00239 box->set_sensitive(false); 00240 #endif 00241 00242 builder->get_widget("sclMcLine", m_scl_mc_line); 00243 m_scl_mc_line->signal_change_value().connect( sigc::mem_fun(*this, &Firestation::mc_on_line_angle_changed) ); 00244 00245 builder->get_widget("btnMcLoadMask", m_btn_mc_load_mask); 00246 m_btn_mc_load_mask->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::mc_load_mask) ); 00247 00248 //builder->get_widget("btnMcStart", m_btn_mc_start); 00249 builder->get_widget("btnCalibLoad", m_btn_mc_load); 00250 builder->get_widget("btnCalibSave", m_btn_mc_save); 00251 builder->get_widget("entCalibDist", m_ent_mc_dist); 00252 builder->get_widget("entCalibOri", m_ent_mc_ori); 00253 builder->get_widget("fcdCalibSave", m_fcd_mc_save); 00254 builder->get_widget("fcdCalibLoad", m_fcd_mc_load); 00255 00256 //m_btn_mc_start->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::mc_start) ); 00257 m_btn_mc_load->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::mc_load) ); 00258 m_btn_mc_save->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::mc_save) ); 00259 00260 builder->get_widget("btnMcSetCenter", m_btn_mc_set_center); 00261 m_btn_mc_set_center->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::mc_set_center) ); 00262 00263 builder->get_widget("btnMcMemorize", m_btn_mc_memorize); 00264 m_btn_mc_memorize->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::mc_memorize) ); 00265 00266 builder->get_widget("btnMcSimulateClicks", m_btn_mc_simulate_clicks); 00267 m_btn_mc_simulate_clicks->signal_clicked().connect( sigc::mem_fun(*this, &Firestation::mc_simulate_clicks) ); 00268 00269 builder->get_widget("entCalibDist", m_ent_mc_dist); 00270 builder->get_widget("entCalibOri", m_ent_mc_ori); 00271 00272 // ---------------------------------------------------------------- 00273 builder->get_widget("fcdMcLoadMask", m_fcd_mc_load_mask); 00274 builder->get_widget("fcdCalibSave", m_fcd_mc_save); 00275 builder->get_widget("fcdCalibLoad", m_fcd_mc_load); 00276 // ---------------------------------------------------------------- 00277 00278 00279 // --- fuse transfer widget --------------------------------------- 00280 m_ftw = new FuseTransferWidget(); 00281 00282 Gtk::TreeView* trv; 00283 builder->get_widget("trvFuseRemoteLuts", trv); 00284 m_ftw->set_remote_lut_list_trv(trv); 00285 builder->get_widget("trvFuseLocalLuts", trv); 00286 m_ftw->set_local_lut_list_trv(trv); 00287 builder->get_widget("imgFuseLocal", img); 00288 m_ftw->set_local_img(img); 00289 builder->get_widget("imgFuseRemote", img); 00290 m_ftw->set_remote_img(img); 00291 builder->get_widget("btnFuseUpload", btn); 00292 m_ftw->set_upload_btn(btn); 00293 builder->get_widget("sclLocalLayerSelector", scl); 00294 m_ftw->set_local_layer_selector(scl); 00295 builder->get_widget("sclRemoteLayerSelector", scl); 00296 m_ftw->set_remote_layer_selector(scl); 00297 // ---------------------------------------------------------------- 00298 00299 00300 // --- fuse image list widget ------------------------------------- 00301 m_filw = new FuseImageListWidget(); 00302 builder->get_widget("trvFuseImageList", trv); 00303 m_filw->set_image_list_trv(trv); 00304 Gtk::CheckButton* chk; 00305 builder->get_widget("chkFuseImageListUpdate", chk); 00306 m_filw->set_auto_update_chk(chk); 00307 builder->get_widget("chkFuseCompression", chk); 00308 m_filw->set_toggle_compression_chk(chk); 00309 m_filw->image_selected().connect( sigc::mem_fun(*this, &Firestation::on_fuse_image_selected) ); 00310 // ---------------------------------------------------------------- 00311 00312 m_yuv_orig_buffer = 0; 00313 m_yuv_draw_buffer = 0; 00314 m_yuv_scaled_buffer = 0; 00315 m_rgb_scaled_buffer = 0; 00316 00317 m_img_width = 0; 00318 m_img_height = 0; 00319 m_img_size = 0; 00320 m_img_cs = CS_UNKNOWN; 00321 00322 m_img_writer = 0; 00323 m_camera = 0; 00324 m_shm_buffer = 0; 00325 00326 m_img_src = SRC_NONE; 00327 m_op_mode = MODE_VIEWER; 00328 00329 m_cont_img_trans = false; 00330 00331 mc_line_angle_deg = 0.0; 00332 00333 m_max_img_width = m_evt_image->get_width(); 00334 m_max_img_height = m_evt_image->get_height(); 00335 m_scaled_img_width = m_evt_image->get_width(); 00336 m_scaled_img_height = m_evt_image->get_height(); 00337 m_scale_factor = 1.0; 00338 00339 m_avahi_thread = new AvahiThread(); 00340 m_avahi_dispatcher = new AvahiDispatcher; 00341 00342 m_avahi_dispatcher->signal_service_added().connect( sigc::mem_fun( *this, &Firestation::on_service_added ) ); 00343 m_avahi_dispatcher->signal_service_removed().connect( sigc::mem_fun( *this, &Firestation::on_service_removed ) ); 00344 00345 m_avahi_thread->watch_service("_fountain._tcp", m_avahi_dispatcher); 00346 m_avahi_thread->start(); 00347 } 00348 00349 /** Destructor. */ 00350 Firestation::~Firestation() 00351 { 00352 if (m_yuv_orig_buffer) free(m_yuv_orig_buffer); 00353 if (m_yuv_draw_buffer) free(m_yuv_draw_buffer); 00354 if (m_yuv_scaled_buffer) free(m_yuv_scaled_buffer); 00355 if (m_rgb_scaled_buffer) free(m_rgb_scaled_buffer); 00356 00357 delete m_camera; 00358 delete m_img_writer; 00359 00360 #ifdef HAVE_MIRROR_CALIB 00361 delete m_calib_tool; 00362 #endif 00363 delete m_ctw; 00364 delete m_ftw; 00365 delete m_filw; 00366 00367 m_avahi_thread->cancel(); 00368 m_avahi_thread->join(); 00369 delete m_avahi_thread; 00370 delete m_avahi_dispatcher; 00371 00372 delete m_wnd_main; 00373 delete m_fcd_open_image; 00374 delete m_fcd_save_image; 00375 delete m_dlg_open_shm; 00376 delete m_dlg_open_fuse; 00377 } 00378 00379 /** Returns reference to main window. 00380 * @return reference to main window 00381 */ 00382 Gtk::Window& 00383 Firestation::get_window() const 00384 { 00385 return *m_wnd_main; 00386 } 00387 00388 /** Exit routine. */ 00389 void 00390 Firestation::exit() 00391 { 00392 if (SRC_NONE != m_img_src) 00393 { m_camera->close(); } 00394 00395 m_wnd_main->hide(); 00396 } 00397 00398 void 00399 Firestation::close_camera() 00400 { 00401 if (SRC_NONE == m_img_src) 00402 { return; } 00403 00404 m_img_src = SRC_NONE; 00405 00406 m_camera->close(); 00407 delete m_camera; 00408 m_camera = 0; 00409 00410 m_img_width = 0; 00411 m_img_height = 0; 00412 m_img_cs = CS_UNKNOWN; 00413 00414 m_img_size = 0; 00415 00416 m_img_image->clear(); 00417 m_img_image->set("gtk-missing-image"); 00418 00419 m_ctw->set_src_buffer(NULL, 0, 0); 00420 m_ctw->set_draw_buffer(NULL); 00421 } 00422 00423 /** Saves the current image. */ 00424 void 00425 Firestation::save_image() 00426 { 00427 if (m_img_src == SRC_NONE) 00428 { return; } 00429 00430 m_fcd_save_image->set_transient_for(*this); 00431 00432 int result = m_fcd_save_image->run(); 00433 00434 switch(result) 00435 { 00436 case(Gtk::RESPONSE_OK): 00437 { 00438 delete m_img_writer; 00439 00440 Glib::ustring filter_name = m_fcd_save_image->get_filter()->get_name(); 00441 if ( Glib::ustring("JPEG") == filter_name ) 00442 { 00443 m_img_writer = new JpegWriter(); 00444 } 00445 else if( Glib::ustring("FVRaw") == filter_name ) 00446 { 00447 m_img_writer = new FvRawWriter(); 00448 } 00449 else 00450 { 00451 cout << "save_file(): unknown file format" << endl; 00452 break; 00453 } 00454 00455 std::string filename = m_fcd_save_image->get_filename(); 00456 m_img_writer->set_filename( filename.c_str() ); 00457 m_img_writer->set_dimensions(m_img_width, m_img_height); 00458 m_img_writer->set_buffer(m_img_cs, m_yuv_orig_buffer); 00459 m_img_writer->write(); 00460 00461 std::cout << "Save file: " << filename << std::endl; 00462 break; 00463 } 00464 00465 case(Gtk::RESPONSE_CANCEL): 00466 break; 00467 00468 default: 00469 break; 00470 } 00471 00472 m_fcd_save_image->hide(); 00473 } 00474 00475 /** Reads in a new image for the current image source. */ 00476 void 00477 Firestation::update_image() 00478 { 00479 if (m_img_src == SRC_NONE) 00480 { return; } 00481 00482 try 00483 { 00484 m_camera->capture(); 00485 convert(m_img_cs, YUV422_PLANAR, 00486 m_camera->buffer(), m_yuv_orig_buffer, 00487 m_img_width, m_img_height); 00488 memcpy(m_yuv_draw_buffer, m_yuv_orig_buffer, 00489 colorspace_buffer_size(YUV422_PLANAR, m_img_width, m_img_height)); 00490 m_camera->dispose_buffer(); 00491 00492 draw_image(); 00493 00494 m_ctw->draw_segmentation_result(); 00495 } 00496 catch (Exception& e) 00497 { 00498 e.print_trace(); 00499 } 00500 } 00501 00502 bool 00503 Firestation::call_update_image() 00504 { 00505 if ( !m_cont_img_trans ) 00506 { return false; } 00507 00508 update_image(); 00509 00510 return true; 00511 } 00512 00513 void 00514 Firestation::enable_cont_img_trans() 00515 { 00516 if (m_cont_img_trans) 00517 { 00518 m_cont_img_trans = false; 00519 return; 00520 } 00521 00522 int timeout = (int) rint( m_spb_update_time->get_value() ); 00523 sigc::connection conn = Glib::signal_timeout().connect( sigc::mem_fun(*this, &Firestation::call_update_image), timeout); 00524 m_cont_img_trans = true; 00525 } 00526 00527 /** Reads in an image from a file. */ 00528 void 00529 Firestation::open_file() 00530 { 00531 m_fcd_open_image->set_action(Gtk::FILE_CHOOSER_ACTION_OPEN); 00532 m_fcd_open_image->set_transient_for(*this); 00533 00534 int result = m_fcd_open_image->run(); 00535 00536 switch(result) 00537 { 00538 case Gtk::RESPONSE_OK: 00539 { 00540 pre_open_img_src(); 00541 00542 std::string filename = m_fcd_open_image->get_filename(); 00543 00544 m_camera = new FileLoader( filename.c_str() ); 00545 m_img_src = SRC_FILE; 00546 post_open_img_src(); 00547 break; 00548 } 00549 00550 case Gtk::RESPONSE_CANCEL: 00551 { 00552 break; 00553 } 00554 00555 default: 00556 { 00557 break; 00558 } 00559 } 00560 00561 m_fcd_open_image->hide(); 00562 } 00563 00564 /** Reads in images from a directory. */ 00565 void 00566 Firestation::open_folder() 00567 { 00568 m_fcd_open_image->set_action(Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER); 00569 m_fcd_open_image->set_transient_for(*this); 00570 00571 int result = m_fcd_open_image->run(); 00572 00573 switch(result) 00574 { 00575 case Gtk::RESPONSE_OK: 00576 { 00577 pre_open_img_src(); 00578 00579 std::string extension; 00580 Glib::ustring filter_name = m_fcd_save_image->get_filter()->get_name(); 00581 if ( Glib::ustring("JPEG") == filter_name ) 00582 { extension = "jpg"; } 00583 else if ( Glib::ustring("FVRaw") == filter_name ) 00584 { extension = "raw"; } 00585 00586 std::string folder = m_fcd_open_image->get_current_folder(); 00587 char* as; 00588 if (asprintf(&as, "file:file:dir=%s:ext=%s", folder.c_str(), extension.c_str()) != -1) { 00589 CameraArgumentParser cap(as); 00590 m_camera = new FileLoader( &cap ); 00591 m_img_src = SRC_FILE; 00592 post_open_img_src(); 00593 free(as); 00594 } else { 00595 printf("Cannot open folder, asprintf() ran out of memory"); 00596 } 00597 00598 break; 00599 } 00600 00601 case Gtk::RESPONSE_CANCEL: 00602 { 00603 break; 00604 } 00605 00606 default: 00607 { 00608 break; 00609 } 00610 } 00611 00612 m_fcd_open_image->hide(); 00613 } 00614 00615 /** Opens a SHM image. */ 00616 void 00617 Firestation::open_shm() 00618 { 00619 unsigned int num_buffers = 0; 00620 SharedMemory::SharedMemoryIterator shmit; 00621 SharedMemoryImageBufferHeader* h = new SharedMemoryImageBufferHeader; 00622 shmit = SharedMemory::find(FIREVISION_SHM_IMAGE_MAGIC_TOKEN, h); 00623 00624 if (shmit == SharedMemory::end()) 00625 { 00626 m_stb_status->push("No SHM images found"); 00627 return; 00628 } 00629 else 00630 { 00631 m_shm_list_store->clear(); 00632 00633 while ( shmit != SharedMemory::end() ) 00634 { 00635 ++num_buffers; 00636 Gtk::TreeModel::Row row = *(m_shm_list_store->append()); 00637 row[m_shm_columns.m_id] = num_buffers; 00638 const SharedMemoryImageBufferHeader* h = (SharedMemoryImageBufferHeader*)*shmit; 00639 row[m_shm_columns.m_name] = h->image_id(); 00640 shmit++; 00641 } 00642 } 00643 00644 m_dlg_open_shm->set_transient_for(*this); 00645 00646 int result = m_dlg_open_shm->run(); 00647 00648 switch(result) 00649 { 00650 case Gtk::RESPONSE_OK: 00651 { 00652 delete m_shm_buffer; 00653 00654 Gtk::TreeModel::Path path; 00655 Gtk::TreeViewColumn* column; 00656 m_trv_shm_image_ids->get_cursor(path, column); 00657 00658 Gtk::TreeModel::iterator iter = m_shm_list_store->get_iter(path); 00659 00660 if (iter) 00661 { 00662 Gtk::TreeModel::Row row = *iter; 00663 if (row) 00664 { 00665 Glib::ustring name = row[m_shm_columns.m_name]; 00666 pre_open_img_src(); 00667 00668 try 00669 { 00670 m_camera = new SharedMemoryCamera( name.c_str() ); 00671 } 00672 catch (Exception& e) 00673 { 00674 e.print_trace(); 00675 } 00676 00677 m_img_src = SRC_SHM; 00678 00679 post_open_img_src(); 00680 } 00681 } 00682 else 00683 { 00684 std::cout << "invalid iter" << std::endl; 00685 } 00686 00687 break; 00688 } 00689 00690 case Gtk::RESPONSE_CANCEL: 00691 break; 00692 00693 default: 00694 break; 00695 } 00696 00697 m_dlg_open_shm->hide(); 00698 } 00699 00700 /** Connects to a FUSE server. */ 00701 void 00702 Firestation::open_fuse() 00703 { 00704 Gtk::TreeModel::Children children = m_fuse_tree_store->children(); 00705 if ( 0 == children.size() ) 00706 { 00707 m_stb_status->push("No FUSE services found"); 00708 return; 00709 } 00710 00711 m_trv_fuse_services->expand_all(); 00712 m_dlg_open_fuse->set_transient_for(*this); 00713 00714 int result = m_dlg_open_fuse->run(); 00715 00716 switch(result) 00717 { 00718 case Gtk::RESPONSE_OK: 00719 { 00720 Gtk::TreeModel::Path path; 00721 Gtk::TreeViewColumn* column; 00722 m_trv_fuse_services->get_cursor(path, column); 00723 00724 Gtk::TreeModel::iterator iter = m_fuse_tree_store->get_iter(path); 00725 00726 if (iter) 00727 { 00728 Gtk::TreeModel::Row row = *iter; 00729 if (row) 00730 { 00731 Glib::ustring hostname = row[m_fuse_columns.m_service_hostname]; 00732 unsigned short int port = row[m_fuse_columns.m_service_port]; 00733 Glib::ustring image_id = row[m_fuse_columns.m_image_id]; 00734 bool jpeg = m_ckb_fuse_jpeg->get_active(); 00735 00736 pre_open_img_src(); 00737 00738 try 00739 { 00740 m_camera = new NetworkCamera(hostname.c_str(), port, image_id.c_str(), jpeg); 00741 m_img_src = SRC_FUSE; 00742 post_open_img_src(); 00743 } 00744 catch (Exception& e) 00745 { 00746 m_img_src = SRC_NONE; 00747 e.print_trace(); 00748 } 00749 } 00750 } 00751 else 00752 { 00753 std::cout << "invalid iter" << std::endl; 00754 } 00755 00756 break; 00757 } 00758 00759 case Gtk::RESPONSE_CANCEL: 00760 break; 00761 00762 default: 00763 break; 00764 } 00765 00766 m_dlg_open_fuse->hide(); 00767 } 00768 00769 void 00770 Firestation::pre_open_img_src() 00771 { 00772 if (SRC_NONE != m_img_src) 00773 { 00774 m_camera->stop(); 00775 m_camera->close(); 00776 00777 delete m_camera; 00778 m_camera = 0; 00779 00780 m_img_src = SRC_NONE; 00781 } 00782 } 00783 00784 /** Stuff that is executed after an image source has been selected. */ 00785 void 00786 Firestation::post_open_img_src() 00787 { 00788 if (m_img_src == SRC_NONE) { return; } 00789 00790 try 00791 { 00792 m_camera->open(); 00793 m_camera->start(); 00794 m_camera->capture(); 00795 m_img_width = m_camera->pixel_width(); 00796 m_img_height = m_camera->pixel_height(); 00797 m_img_cs = m_camera->colorspace(); 00798 00799 m_img_size = colorspace_buffer_size( m_img_cs, 00800 m_img_width, 00801 m_img_height ); 00802 00803 m_yuv_orig_buffer = malloc_buffer(YUV422_PLANAR, m_img_width, m_img_height); 00804 m_yuv_draw_buffer = malloc_buffer(YUV422_PLANAR, m_img_width, m_img_height); 00805 00806 convert(m_img_cs, YUV422_PLANAR, 00807 m_camera->buffer(), m_yuv_orig_buffer, 00808 m_img_width, m_img_height); 00809 memcpy(m_yuv_draw_buffer, m_yuv_orig_buffer, 00810 colorspace_buffer_size(YUV422_PLANAR, m_img_width, m_img_height)); 00811 00812 m_camera->dispose_buffer(); 00813 00814 m_tbtn_update->set_sensitive(true); 00815 m_tbtn_save->set_sensitive(true); 00816 00817 draw_image(); 00818 00819 m_ctw->set_src_buffer(m_yuv_orig_buffer, m_img_width, m_img_height); 00820 m_ctw->set_draw_buffer(m_yuv_draw_buffer); 00821 m_ctw->draw_segmentation_result(); 00822 00823 mc_draw_line(); 00824 } 00825 catch (Exception& e) 00826 { 00827 e.print_trace(); 00828 printf("Opening camera failed.\n"); 00829 } 00830 00831 } 00832 00833 void 00834 Firestation::on_fuse_image_selected() 00835 { 00836 string host_name; 00837 unsigned short port; 00838 string image_id; 00839 bool compression; 00840 00841 m_filw->get_selected_image(host_name, port, image_id, compression); 00842 00843 pre_open_img_src(); 00844 00845 try 00846 { 00847 m_camera = new NetworkCamera( host_name.c_str(), port, image_id.c_str(), compression ); 00848 m_img_src = SRC_FUSE; 00849 } 00850 catch (Exception& e) 00851 { 00852 m_img_src = SRC_NONE; 00853 e.print_trace(); 00854 } 00855 00856 post_open_img_src(); 00857 } 00858 00859 void 00860 Firestation::on_colormap_updated() 00861 { 00862 m_ftw->set_current_colormap( m_ctw->get_colormap() ); 00863 } 00864 00865 /** Draws the image. */ 00866 void 00867 Firestation::draw_image() 00868 { 00869 if ( m_img_src == SRC_NONE ) { return; } 00870 00871 LossyScaler scaler; 00872 scaler.set_original_buffer( m_yuv_draw_buffer ); 00873 scaler.set_original_dimensions(m_img_width, m_img_height); 00874 scaler.set_scaled_dimensions(m_max_img_width, m_max_img_height); 00875 00876 unsigned int scaled_width = scaler.needed_scaled_width(); 00877 unsigned int scaled_height = scaler.needed_scaled_height(); 00878 00879 if (scaled_width != m_scaled_img_width || scaled_height != m_scaled_img_height) 00880 { 00881 m_scaled_img_width = scaled_width; 00882 m_scaled_img_height = scaled_height; 00883 m_scale_factor = scaler.get_scale_factor(); 00884 } 00885 00886 if (m_rgb_scaled_buffer) free(m_rgb_scaled_buffer); 00887 if (m_yuv_scaled_buffer) free(m_yuv_scaled_buffer); 00888 m_yuv_scaled_buffer = malloc_buffer(YUV422_PLANAR, m_scaled_img_width, 00889 m_scaled_img_height); 00890 scaler.set_scaled_buffer(m_yuv_scaled_buffer); 00891 scaler.scale(); 00892 00893 if (m_btn_ct_seg->get_active()) { 00894 unsigned int sld_img_size = m_scaled_img_width * m_scaled_img_height; 00895 unsigned char u_seg = 255 / (unsigned int)pow(2, m_spbtn_width->get_value()); 00896 unsigned char v_seg = 255 / (unsigned int)pow(2, m_spbtn_height->get_value()); 00897 unsigned int u = 0; 00898 for (u = sld_img_size; u < sld_img_size + sld_img_size / 2; ++u) { 00899 m_yuv_scaled_buffer[u] = (m_yuv_scaled_buffer[u] / u_seg) * u_seg; 00900 } 00901 00902 for (; u < 2 * sld_img_size; ++u) { 00903 m_yuv_scaled_buffer[u] = (m_yuv_scaled_buffer[u] / v_seg) * v_seg; 00904 } 00905 } 00906 00907 if ( m_img_src == SRC_SHM ) 00908 { 00909 SharedMemoryCamera* shm_camera = dynamic_cast<SharedMemoryCamera*>(m_camera); 00910 if ( shm_camera->shared_memory_image_buffer()->circle_found() ) 00911 { 00912 Drawer drawer; 00913 drawer.set_buffer(m_yuv_scaled_buffer, m_scaled_img_width, m_scaled_img_height); 00914 drawer.set_color(YUV_t::white()); 00915 unsigned int roi_x = (unsigned int) rint( shm_camera->shared_memory_image_buffer()->roi_x() * m_scale_factor ); 00916 unsigned int roi_y = (unsigned int) rint( shm_camera->shared_memory_image_buffer()->roi_y() * m_scale_factor ); 00917 unsigned int roi_width = (unsigned int) rint( shm_camera->shared_memory_image_buffer()->roi_width() * m_scale_factor ); 00918 unsigned int roi_height = (unsigned int) rint( shm_camera->shared_memory_image_buffer()->roi_height() * m_scale_factor ); 00919 drawer.draw_rectangle( roi_x, roi_y, roi_width, roi_height ); 00920 } 00921 } 00922 00923 m_rgb_scaled_buffer = (unsigned char*) malloc( colorspace_buffer_size( RGB, 00924 m_scaled_img_width, 00925 m_scaled_img_height ) ); 00926 00927 convert( YUV422_PLANAR, RGB, 00928 m_yuv_scaled_buffer, m_rgb_scaled_buffer, 00929 m_scaled_img_width, m_scaled_img_height ); 00930 00931 Glib::RefPtr<Gdk::Pixbuf> image = Gdk::Pixbuf::create_from_data( m_rgb_scaled_buffer, 00932 Gdk::COLORSPACE_RGB, 00933 false, 00934 8, 00935 m_scaled_img_width, 00936 m_scaled_img_height, 00937 3 * m_scaled_img_width ); 00938 00939 m_img_image->set(image); 00940 } 00941 00942 /** Signal handler that is called whenever the window size is changed. 00943 * @param allocation a Gtk allocation 00944 */ 00945 void 00946 Firestation::resize_image(Gtk::Allocation& allocation) 00947 { 00948 unsigned int new_width = (unsigned int) allocation.get_width(); 00949 unsigned int new_height = (unsigned int) allocation.get_height(); 00950 00951 if (new_width != m_max_img_width || new_height != m_max_img_height) 00952 { 00953 m_max_img_width = new_width; 00954 m_max_img_height = new_height; 00955 draw_image(); 00956 } 00957 } 00958 00959 /** Handles mouse clicks in the image area. 00960 * @param event a Gtk event 00961 * @return true if signal was handled 00962 */ 00963 bool 00964 Firestation::image_click(GdkEventButton* event) 00965 { 00966 unsigned int offset_x; 00967 unsigned int offset_y; 00968 00969 offset_x = (m_max_img_width - m_scaled_img_width) / 2; 00970 offset_y = (m_max_img_height - m_scaled_img_height) / 2; 00971 00972 offset_x = offset_x > m_max_img_width ? 0 : offset_x; 00973 offset_y = offset_y > m_max_img_height ? 0 : offset_y; 00974 00975 unsigned int image_x; 00976 unsigned int image_y; 00977 00978 if (event != NULL) { 00979 image_x = (unsigned int)rint( (event->x - offset_x) / m_scale_factor); 00980 image_y = (unsigned int)rint( (event->y - offset_y) / m_scale_factor); 00981 } else { 00982 image_x = 0; 00983 image_y = 0; 00984 } 00985 00986 if ( image_x < 0 || image_x > m_img_width || 00987 image_y < 0 || image_y > m_img_height ) 00988 { return true; } 00989 00990 switch (m_op_mode) 00991 { 00992 case MODE_VIEWER: 00993 if (m_img_src != SRC_NONE) 00994 { 00995 register unsigned char y; 00996 register unsigned char u; 00997 register unsigned char v; 00998 YUV422_PLANAR_YUV( m_yuv_orig_buffer, 00999 m_img_width, 01000 m_img_height, 01001 image_x, 01002 image_y, 01003 y, u, v ); 01004 printf( "Y=%d U=%d Y=%d @ (%d, %d)\n", 01005 (unsigned int) y, (unsigned int) u, (unsigned int) v, 01006 image_x, image_y ); 01007 } 01008 break; 01009 01010 case MODE_COLOR_TRAIN: 01011 m_ctw->click(image_x, image_y, event->button); 01012 draw_image(); 01013 break; 01014 01015 case MODE_MIRROR_CALIB: 01016 { 01017 #ifdef HAVE_MIRROR_CALIB 01018 if (m_btn_mc_set_center->get_active()) { 01019 m_calib_tool->set_center(image_x, image_y); 01020 m_btn_mc_set_center->set_active(false); 01021 mc_draw_line(); 01022 printf("Setting center to %d, %d\n", image_x, image_y); 01023 } else { 01024 printf("Using center to %d, %d\n", m_calib_tool->center_x(), m_calib_tool->center_y()); 01025 m_calib_tool->next_step(); 01026 const unsigned char* last_yuv = m_calib_tool->get_last_yuv_buffer(); 01027 memcpy(m_yuv_draw_buffer, last_yuv, m_img_size); 01028 memcpy(m_yuv_orig_buffer, last_yuv, m_img_size); 01029 m_calib_tool->draw_mark_lines(m_yuv_draw_buffer); 01030 draw_image(); 01031 m_stb_status->push(m_calib_tool->get_state_description()); 01032 } 01033 #else 01034 printf("IPP and OpenCV not installed; mirror calibration does not work.\n"); 01035 #endif 01036 break; 01037 } 01038 01039 case MODE_MIRROR_CALIB_EVAL: 01040 { 01041 #ifdef HAVE_MIRROR_CALIB 01042 float dist; 01043 float phi; 01044 m_calib_tool->eval(image_x, image_y, &dist, &phi); 01045 phi = normalize_mirror_rad(phi); 01046 printf("(%d, %d) = POLAR(%.2f deg, %.2f meters)\n", 01047 image_x, image_y, 01048 rad2deg(phi), dist); 01049 //printf("Distance: %2f\t Phi: %2f\n", dist, phi); 01050 #else 01051 printf("IPP and OpenCV not installed; mirror calibration does not work.\n"); 01052 #endif 01053 break; 01054 } 01055 01056 default: 01057 break; 01058 } 01059 01060 return true; 01061 } 01062 01063 /** Starts the color training. */ 01064 void 01065 Firestation::ct_start() 01066 { 01067 if (m_op_mode == MODE_COLOR_TRAIN) 01068 { 01069 m_op_mode = MODE_VIEWER; 01070 m_stb_status->push("Leaving color training mode"); 01071 } 01072 else 01073 { 01074 if (m_img_src != SRC_NONE) 01075 { 01076 m_ctw->set_fg_object( ct_get_fg_object() ); 01077 01078 m_op_mode = MODE_COLOR_TRAIN; 01079 01080 m_stb_status->push("Entering color training mode"); 01081 } 01082 } 01083 } 01084 01085 hint_t 01086 Firestation::ct_get_fg_object() 01087 { 01088 int active = m_cmb_ct_type->get_active_row_number(); 01089 switch(active) 01090 { 01091 case 0: //Ball 01092 return H_BALL; 01093 01094 case 1: //Field 01095 return H_FIELD; 01096 01097 case 2: //Lines 01098 return H_LINE; 01099 01100 case 3: //Robot (Team A or all) 01101 return H_ROBOT; 01102 01103 case 4: //Robot (Team B) 01104 return H_ROBOT_OPP; 01105 01106 case 5: //Goal (yellow) 01107 return H_GOAL_YELLOW; 01108 01109 case 6: //Goal (sky-blue) 01110 return H_GOAL_BLUE; 01111 01112 case 7: //Background 01113 return H_UNKNOWN; 01114 01115 default: 01116 printf("ct_get_fg_object(): UNKNOWN\n"); 01117 return H_UNKNOWN; 01118 } 01119 } 01120 01121 void 01122 Firestation::ct_object_changed() 01123 { 01124 hint_t object = ct_get_fg_object(); 01125 m_ctw->set_fg_object(object); 01126 } 01127 01128 void 01129 Firestation::mc_draw_line() 01130 { 01131 if (m_img_src != SRC_NONE) { 01132 #ifdef HAVE_MIRROR_CALIB 01133 memcpy(m_yuv_draw_buffer, m_yuv_orig_buffer, m_img_size); 01134 MirrorCalibTool::draw_line(m_yuv_draw_buffer, 01135 mc_line_angle_deg, 01136 m_calib_tool->center_x(), 01137 m_calib_tool->center_y(), 01138 m_img_width, 01139 m_img_height); 01140 draw_image(); 01141 #else 01142 printf("IPP and OpenCV not installed; mirror calibration does not work.\n"); 01143 #endif 01144 } 01145 } 01146 01147 bool 01148 Firestation::mc_on_line_angle_changed(Gtk::ScrollType scroll, double value) 01149 { 01150 mc_line_angle_deg = -1.0f * value; 01151 mc_line_angle_deg = 01152 rad2deg(normalize_mirror_rad(deg2rad(mc_line_angle_deg))); 01153 // Why -1.0f * value? 01154 // We want to display angles from the robot's real-world perspective. 01155 // We want to calculate with angles from the (mirrored!) image's perspective. 01156 // So when the user chooses 90 degrees, he wants to look to the left from the 01157 // robots perspective. But due to the mirroring, that's the right side in the 01158 // image, so we take -90 degrees. 01159 mc_draw_line(); 01160 return true; 01161 } 01162 01163 void 01164 Firestation::mc_load_mask() 01165 { 01166 m_fcd_mc_load_mask->set_transient_for(*this); 01167 01168 #if GTK_VERSION_GE(3,0) 01169 Glib::RefPtr<Gtk::FileFilter> filter_mirror = Gtk::FileFilter::create(); 01170 #else 01171 Gtk::FileFilter *filter_mirror = Gtk::manage(new Gtk::FileFilter()); 01172 #endif 01173 filter_mirror->set_name("Robot Mask"); 01174 filter_mirror->add_pattern("*.pnm"); 01175 #if GTK_VERSION_GE(3,0) 01176 m_fcd_mc_load_mask->add_filter(filter_mirror); 01177 #else 01178 m_fcd_mc_load_mask->add_filter(*filter_mirror); 01179 #endif 01180 01181 int result = m_fcd_mc_load_mask->run(); 01182 01183 switch(result) 01184 { 01185 case Gtk::RESPONSE_OK: 01186 { 01187 #ifdef HAVE_MIRROR_CALIB 01188 std::string filename = m_fcd_mc_load_mask->get_filename(); 01189 m_calib_tool->load_mask( filename.c_str() ); 01190 //m_op_mode = MODE_MIRROR_CALIB_EVAL; 01191 #else 01192 printf("IPP and OpenCV not installed; mirror calibration does not work.\n"); 01193 #endif 01194 break; 01195 } 01196 case Gtk::RESPONSE_CANCEL: 01197 break; 01198 default: 01199 break; 01200 } 01201 01202 m_fcd_mc_load_mask->hide(); 01203 } 01204 01205 /** Enters MODE_MIRROR_CALIB mode which waits for a click to mark the 01206 * preliminary center of the image. */ 01207 void 01208 Firestation::mc_set_center() 01209 { 01210 m_op_mode = MODE_MIRROR_CALIB; 01211 } 01212 01213 /** Start the mirror calibration process. */ 01214 void 01215 Firestation::mc_memorize() 01216 { 01217 /* if (m_op_mode == MODE_MIRROR_CALIB) 01218 { 01219 m_op_mode = MODE_VIEWER; 01220 m_stb_status->push("Leaving mirror calibration mode"); 01221 } 01222 else */ if (m_img_src != SRC_NONE) 01223 { 01224 #ifdef HAVE_MIRROR_CALIB 01225 double ori = mc_line_angle_deg; 01226 std::cout << "Starting calibration for ori = " << ori << std::endl; 01227 m_calib_tool->push_back(m_yuv_orig_buffer, m_img_size, 01228 m_img_width, m_img_height, deg2rad(ori)); 01229 m_op_mode = MODE_MIRROR_CALIB; 01230 std::cout << "Initialization for ori = " << ori << " completed" << std::endl; 01231 01232 mc_line_angle_deg -= 120.0; 01233 mc_line_angle_deg = 01234 rad2deg(normalize_mirror_rad(deg2rad(mc_line_angle_deg))); 01235 m_scl_mc_line->set_value(-1.0f * mc_line_angle_deg); 01236 // Why -1.0f * mc_line_angle_deg? 01237 // We want to display angles from the robot's real-world perspective. 01238 // We want to calculate with angles from the (mirrored!) image's perspective. 01239 // So when the user chooses 90 degrees, he wants to look to the left from the 01240 // robots perspective. But due to the mirroring, that's the right side in the 01241 // image, so we take -90 degrees. 01242 mc_draw_line(); 01243 #else 01244 printf("IPP and OpenCV not installed; mirror calibration does not work.\n"); 01245 #endif 01246 } 01247 } 01248 01249 /** Start the mirror calibration process. */ 01250 void 01251 Firestation::mc_simulate_clicks() 01252 { 01253 for (int i = 1; i <= 3; ++i) { 01254 image_click(NULL); // SHARPENING 01255 for (int j = 1; j <= 8; ++j) { image_click(NULL); } // EDGE_DETECTION 01256 for (int j = 1; j <= 2*8; ++j) { image_click(NULL); } // COMBINATION 01257 image_click(NULL); // PRE_MARKING 01258 image_click(NULL); // FINAL_MARKING 01259 } 01260 } 01261 01262 /** Load mirror calibration data from a file. */ 01263 void 01264 Firestation::mc_load() 01265 { 01266 m_fcd_mc_load->set_transient_for(*this); 01267 01268 #if GTK_VERSION_GE(3,0) 01269 Glib::RefPtr<Gtk::FileFilter> filter_mirror = Gtk::FileFilter::create(); 01270 #else 01271 Gtk::FileFilter *filter_mirror = Gtk::manage(new Gtk::FileFilter()); 01272 #endif 01273 filter_mirror->set_name("Mirror Calibration"); 01274 filter_mirror->add_pattern("*.mirror"); 01275 filter_mirror->add_pattern("*.bulb"); 01276 #if GTK_VERSION_GE(3,0) 01277 m_fcd_mc_load->add_filter(filter_mirror); 01278 #else 01279 m_fcd_mc_load->add_filter(*filter_mirror); 01280 #endif 01281 01282 int result = m_fcd_mc_load->run(); 01283 01284 switch(result) 01285 { 01286 case Gtk::RESPONSE_OK: 01287 { 01288 #ifdef HAVE_MIRROR_CALIB 01289 std::string filename = m_fcd_mc_load->get_filename(); 01290 m_calib_tool->load( filename.c_str() ); 01291 m_op_mode = MODE_MIRROR_CALIB_EVAL; 01292 #else 01293 printf("IPP and OpenCV not installed; mirror calibration does not work.\n"); 01294 #endif 01295 break; 01296 } 01297 case Gtk::RESPONSE_CANCEL: 01298 break; 01299 default: 01300 break; 01301 } 01302 01303 m_fcd_mc_load->hide(); 01304 } 01305 01306 /** Save calibration data to a file. */ 01307 void 01308 Firestation::mc_save() 01309 { 01310 m_fcd_mc_save->set_transient_for(*this); 01311 01312 int result = m_fcd_mc_save->run(); 01313 01314 switch(result) 01315 { 01316 case(Gtk::RESPONSE_OK): 01317 { 01318 #ifdef HAVE_MIRROR_CALIB 01319 std::string filename = m_fcd_mc_save->get_filename(); 01320 01321 m_calib_tool->save( filename.c_str() ); 01322 #else 01323 printf("IPP and OpenCV not installed; mirror calibration does not work.\n"); 01324 #endif 01325 break; 01326 } 01327 01328 case(Gtk::RESPONSE_CANCEL): 01329 break; 01330 01331 default: 01332 break; 01333 } 01334 01335 m_fcd_mc_save->hide(); 01336 01337 } 01338 01339 void 01340 Firestation::on_service_added( NetworkService* service ) 01341 { 01342 const char* host = service->host(); 01343 const char* name = service->name(); 01344 const char* type = service->type(); 01345 const char* domain = service->domain(); 01346 unsigned short int port = service->port(); 01347 01348 std::vector<FUSE_imageinfo_t> image_list; 01349 NetworkCamera cam(host, port); 01350 try 01351 { 01352 cam.open(); 01353 cam.start(); 01354 image_list = cam.image_list(); 01355 } 01356 catch (Exception& e) 01357 { 01358 e.append("Could not open camera on %s:%d", host, port); 01359 e.print_trace(); 01360 return; 01361 } 01362 cam.close(); 01363 01364 #ifdef DEBUG_PRINT 01365 printf("%zu images available on host %s.\n", image_list.size(), host); 01366 #endif /* DEBUG_PRINT */ 01367 01368 std::vector<FUSE_imageinfo_t>::iterator fit; 01369 01370 Gtk::TreeModel::Children children = m_fuse_tree_store->children(); 01371 Gtk::TreeModel::Row row = *(m_fuse_tree_store->append()); 01372 row[m_fuse_columns.m_id] = children.size(); 01373 row[m_fuse_columns.m_name] = Glib::ustring(name); 01374 row[m_fuse_columns.m_service_name] = Glib::ustring(name); 01375 row[m_fuse_columns.m_service_type] = Glib::ustring(type); 01376 row[m_fuse_columns.m_service_domain] = Glib::ustring(domain); 01377 row[m_fuse_columns.m_service_hostname] = Glib::ustring(host); 01378 row[m_fuse_columns.m_service_port] = port; 01379 01380 for (fit = image_list.begin(); fit != image_list.end(); ++fit) 01381 { 01382 Gtk::TreeModel::Row childrow = *(m_fuse_tree_store->append(row.children())); 01383 childrow[m_fuse_columns.m_name] = Glib::ustring(fit->image_id); 01384 childrow[m_fuse_columns.m_service_name] = Glib::ustring(name); 01385 childrow[m_fuse_columns.m_service_type] = Glib::ustring(type); 01386 childrow[m_fuse_columns.m_service_domain] = Glib::ustring(domain); 01387 childrow[m_fuse_columns.m_service_hostname] = Glib::ustring(host); 01388 childrow[m_fuse_columns.m_service_port] = port; 01389 childrow[m_fuse_columns.m_image_id] = Glib::ustring(fit->image_id); 01390 childrow[m_fuse_columns.m_image_width] = fit->width; 01391 childrow[m_fuse_columns.m_image_height] = fit->height; 01392 childrow[m_fuse_columns.m_image_colorspace] = Glib::ustring( colorspace_to_string((colorspace_t) fit->colorspace) ); 01393 } 01394 01395 m_ftw->add_fountain_service(name, host, port); 01396 m_filw->add_fountain_service(name, host, port); 01397 } 01398 01399 void 01400 Firestation::on_service_removed( NetworkService* service ) 01401 { 01402 const char* name = service->name(); 01403 const char* type = service->type(); 01404 const char* domain = service->domain(); 01405 01406 Gtk::TreeModel::Children children = m_fuse_tree_store->children(); 01407 Gtk::TreeModel::iterator rit; 01408 for (rit = children.begin(); rit != children.end(); ++rit) 01409 { 01410 Glib::ustring n = (*rit)[m_fuse_columns.m_service_name]; 01411 Glib::ustring t = (*rit)[m_fuse_columns.m_service_type]; 01412 Glib::ustring d = (*rit)[m_fuse_columns.m_service_domain]; 01413 01414 if ( strcmp( n.c_str(), name) == 0 && 01415 strcmp( t.c_str(), type) == 0 && 01416 strcmp( d.c_str(), domain) == 0 ) 01417 { 01418 m_fuse_tree_store->erase(rit); 01419 } 01420 } 01421 01422 m_ftw->remove_fountain_service(name); 01423 m_filw->remove_fountain_service(name); 01424 }