Fawkes API Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * fuse_viewer_gui.cpp - Fuse (network camera) Viewer Gui 00004 * 00005 * Created: Thu Dec 18 14:16:23 2008 00006 * Copyright 2008-2009 Christof Rath <c.rath@student.tugraz.at> 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 "fuse_viewer_gui.h" 00024 00025 #include <gui_utils/avahi_dispatcher.h> 00026 #include <core/exception.h> 00027 #include <fvwidgets/fuse_image_list_widget.h> 00028 #include <fvwidgets/image_widget.h> 00029 #include <cams/net.h> 00030 00031 #include <cstring> 00032 00033 using namespace fawkes; 00034 using namespace firevision; 00035 00036 /** @class FuseViewerGtkWindow "fuse_viewer_gui.h" 00037 * Fawkes network camera viewer. 00038 * 00039 * Currently the image refreshes 300ms after the retrieval and display of the 00040 * last refresh (e.g. every 300ms in an ideal system) 00041 * The FUSE list doesn't get updated (due to a bug?), restarting the fvfountain 00042 * plugin on the remote host does the job. 00043 * 00044 * @author Christof Rath 00045 */ 00046 00047 /** Constructor. 00048 * @param cobject C base object 00049 * @param ref_xml Glade XML 00050 */ 00051 FuseViewerGtkWindow::FuseViewerGtkWindow(BaseObjectType* cobject, 00052 const Glib::RefPtr<Gnome::Glade::Xml> ref_xml) 00053 : Gtk::Window(cobject) 00054 { 00055 ref_xml->get_widget("swFuseList", __image_list_scroll); 00056 ref_xml->get_widget("vpImage", __image_viewport); 00057 ref_xml->get_widget("afSaveType", __save_box); 00058 ref_xml->get_widget("fcbSaveTo", __save_filechooser); 00059 ref_xml->get_widget("cbtAutoSave", __auto_save); 00060 ref_xml->get_widget("btSaveImage", __save_btn); 00061 ref_xml->get_widget("stb", __statusbar); 00062 00063 __img_list_widget = Gtk::manage(new FuseImageListWidget()); 00064 __img_list_widget->image_selected().connect( sigc::mem_fun(*this, &FuseViewerGtkWindow::on_fuse_image_selected) ); 00065 // __img_list_widget->set_auto_update(true, 1); 00066 __image_list_scroll->add(*__img_list_widget); 00067 00068 __save_type = Gtk::manage(new Gtk::ComboBoxText); 00069 __save_box->add(*__save_type); 00070 00071 Gdk::Pixbuf::SListHandle_PixbufFormat fmts = Gdk::Pixbuf::get_formats(); 00072 Gdk::Pixbuf::SListHandle_PixbufFormat::const_iterator it = fmts.begin(); 00073 __save_type->append_text("Don't save"); 00074 for (; it != fmts.end(); ++it) { 00075 if ((*it).is_writable()) { 00076 __save_type->append_text((*it).get_name()); 00077 } 00078 } 00079 00080 __save_type->set_active(0); 00081 __save_type->set_sensitive(false); 00082 __save_type->signal_changed().connect( sigc::mem_fun(*this, &FuseViewerGtkWindow::on_save_type_change) ); 00083 __auto_save->signal_toggled().connect( sigc::mem_fun(*this, &FuseViewerGtkWindow::on_auto_save_cbt_change) ); 00084 __save_btn->signal_clicked().connect( sigc::mem_fun(*this, &FuseViewerGtkWindow::on_save_image_clicked) ); 00085 show_all_children(); 00086 00087 __cur_service_name = ""; 00088 __img_num = 0; 00089 __img_widget = NULL; 00090 __cam = NULL; 00091 00092 set_status(""); 00093 00094 __avahi_thread = new AvahiThread(); 00095 __avahi_dispatcher = new AvahiDispatcher; 00096 00097 __avahi_dispatcher->signal_service_added().connect( sigc::mem_fun( *this, &FuseViewerGtkWindow::on_service_added ) ); 00098 __avahi_dispatcher->signal_service_removed().connect( sigc::mem_fun( *this, &FuseViewerGtkWindow::on_service_removed ) ); 00099 00100 __avahi_thread->watch_service("_fountain._tcp", __avahi_dispatcher); 00101 __avahi_thread->start(); 00102 } 00103 00104 /** Destructor. */ 00105 FuseViewerGtkWindow::~FuseViewerGtkWindow() 00106 { 00107 delete __avahi_thread; 00108 delete __avahi_dispatcher; 00109 } 00110 00111 /** Signal handler called after AvahiThread detects a new NetworkService */ 00112 void 00113 FuseViewerGtkWindow::on_service_added(fawkes::NetworkService* service) 00114 { 00115 const char* name = service->name(); 00116 const char* host = service->host(); 00117 00118 __host_service_map[host] = name; 00119 __img_list_widget->add_fountain_service( 00120 name, 00121 host, 00122 service->port()); 00123 } 00124 00125 /** Signal handler called after AvahiThread detects a NetworkService removal */ 00126 void 00127 FuseViewerGtkWindow::on_service_removed( fawkes::NetworkService* service ) 00128 { 00129 __img_list_widget->remove_fountain_service( service->name() ); 00130 00131 if (__cur_service_name == service->name()) { 00132 close_image(); 00133 } 00134 00135 std::map<std::string, std::string>::const_iterator it = __host_service_map.begin(); 00136 for (; it != __host_service_map.end(); ++it) { 00137 if (__cur_service_name == it->second) { 00138 __host_service_map.erase(it->first); 00139 break; 00140 } 00141 } 00142 } 00143 00144 /** Signal handler that is called when an image is selected in the image list */ 00145 void 00146 FuseViewerGtkWindow::on_fuse_image_selected() 00147 { 00148 __img_list_widget->set_sensitive(Gtk::SENSITIVITY_OFF); 00149 std::string host; 00150 unsigned short port; 00151 std::string image_id; 00152 bool compression; 00153 00154 __img_list_widget->get_selected_image(host, port, image_id, compression); 00155 00156 close_image(); 00157 00158 try { 00159 __cam = new NetworkCamera( host.c_str(), port, image_id.c_str(), compression ); 00160 __cam->open(); 00161 __cam->start(); 00162 __cur_service_name = __host_service_map[host]; 00163 00164 __img_widget = new ImageWidget(__cam, 300); 00165 __image_viewport->add(*__img_widget); 00166 __image_viewport->set_size_request(__cam->pixel_width(), __cam->pixel_height()); 00167 show_all_children(); 00168 __save_type->set_sensitive(Gtk::SENSITIVITY_ON); 00169 00170 set_status(image_id, host, port); 00171 } 00172 catch (Exception& e) { 00173 __cam = NULL; 00174 e.print_trace(); 00175 } 00176 00177 __img_list_widget->set_sensitive(Gtk::SENSITIVITY_ON); 00178 } 00179 00180 /** Signal handler that is called if the 'Auto save' checkbox status changes */ 00181 void 00182 FuseViewerGtkWindow::on_auto_save_cbt_change() 00183 { 00184 if (__auto_save->get_active()) { 00185 __save_btn->set_sensitive(false); 00186 00187 __img_widget->save_on_refresh_cam(true, 00188 __save_filechooser->get_current_folder(), 00189 __save_type->get_active_text(), 00190 __img_num); 00191 } 00192 else { 00193 __img_widget->save_on_refresh_cam(false); 00194 __img_num = __img_widget->get_image_num(); 00195 00196 __save_btn->set_sensitive(true); 00197 } 00198 } 00199 00200 /** Signal handler that is called when the fileformat to save images changes */ 00201 void 00202 FuseViewerGtkWindow::on_save_type_change() 00203 { 00204 if (__save_type->get_active_row_number()) { 00205 __auto_save->set_sensitive(true); 00206 00207 if (__auto_save->get_active()) __img_num = __img_widget->get_image_num(); 00208 on_auto_save_cbt_change(); 00209 } 00210 else { 00211 __auto_save->set_active(false); 00212 __auto_save->set_sensitive(false); 00213 __save_btn->set_sensitive(false); 00214 } 00215 } 00216 00217 /** Signal handler that is called when the 'Save image' button is pressed */ 00218 void 00219 FuseViewerGtkWindow::on_save_image_clicked() 00220 { 00221 char *ctmp; 00222 if (asprintf(&ctmp, "%s/%06u.%s", __save_filechooser->get_current_folder().c_str(), 00223 ++__img_num, __save_type->get_active_text().c_str()) != -1) { 00224 Glib::ustring fn = ctmp; 00225 free(ctmp); 00226 00227 __img_widget->save_image(fn, __save_type->get_active_text()); 00228 } else { 00229 printf("Could not save file, asprintf() ran out of memory"); 00230 } 00231 } 00232 00233 /** 00234 * Sets the current status (to the statusbar) 00235 * @param img_id the id of the current selected image 00236 * @param host the host that provides the image 00237 * @param port the port to transfer the image 00238 */ 00239 void 00240 FuseViewerGtkWindow::set_status(std::string img_id, std::string host, unsigned short port) 00241 { 00242 if (!img_id.length()) { 00243 __statusbar->push(Glib::ustring("Not connected.")); 00244 } 00245 else { 00246 char *ctmp = NULL; 00247 if (asprintf(&ctmp, "Host: %s:%u\tId: %s", 00248 host.c_str(), port, img_id.c_str())) { 00249 __statusbar->push(Glib::ustring(ctmp)); 00250 free(ctmp); 00251 } 00252 } 00253 } 00254 00255 /** Closes the image and the camera */ 00256 void 00257 FuseViewerGtkWindow::close_image() 00258 { 00259 if (__img_widget) { 00260 __image_viewport->remove(); 00261 delete __img_widget; 00262 __img_widget = NULL; 00263 __save_type->set_sensitive(Gtk::SENSITIVITY_OFF); 00264 } 00265 00266 if (__cam) { 00267 __cam->stop(); 00268 __cam->close(); 00269 delete __cam; 00270 __cam = NULL; 00271 } 00272 00273 set_status(""); 00274 } 00275