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 <fvcams/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 builder Gtk::Builder 00050 */ 00051 FuseViewerGtkWindow::FuseViewerGtkWindow(BaseObjectType* cobject, 00052 const Glib::RefPtr<Gtk::Builder> builder) 00053 : Gtk::Window(cobject) 00054 { 00055 builder->get_widget("swFuseList", __image_list_scroll); 00056 builder->get_widget("vpImage", __image_viewport); 00057 builder->get_widget("afSaveType", __save_box); 00058 builder->get_widget("fcbSaveTo", __save_filechooser); 00059 builder->get_widget("cbtAutoSave", __auto_save); 00060 builder->get_widget("btSaveImage", __save_btn); 00061 builder->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 std::vector<Gdk::PixbufFormat> fmts = Gdk::Pixbuf::get_formats(); 00072 std::vector<Gdk::PixbufFormat>::const_iterator it = fmts.begin(); 00073 #if GTK_VERSION_GE(3,0) 00074 __save_type->append("Don't save"); 00075 #else 00076 __save_type->append_text("Don't save"); 00077 #endif 00078 for (; it != fmts.end(); ++it) { 00079 if ((*it).is_writable()) { 00080 #if GTK_VERSION_GE(3,0) 00081 __save_type->append((*it).get_name()); 00082 #else 00083 __save_type->append_text((*it).get_name()); 00084 #endif 00085 } 00086 } 00087 00088 __save_type->set_active(0); 00089 __save_type->set_sensitive(false); 00090 __save_type->signal_changed().connect( sigc::mem_fun(*this, &FuseViewerGtkWindow::on_save_type_change) ); 00091 __auto_save->signal_toggled().connect( sigc::mem_fun(*this, &FuseViewerGtkWindow::on_auto_save_cbt_change) ); 00092 __save_btn->signal_clicked().connect( sigc::mem_fun(*this, &FuseViewerGtkWindow::on_save_image_clicked) ); 00093 show_all_children(); 00094 00095 __cur_service_name = ""; 00096 __img_num = 0; 00097 __img_widget = NULL; 00098 __cam = NULL; 00099 00100 set_status(""); 00101 00102 __avahi_thread = new AvahiThread(); 00103 __avahi_dispatcher = new AvahiDispatcher; 00104 00105 __avahi_dispatcher->signal_service_added().connect( sigc::mem_fun( *this, &FuseViewerGtkWindow::on_service_added ) ); 00106 __avahi_dispatcher->signal_service_removed().connect( sigc::mem_fun( *this, &FuseViewerGtkWindow::on_service_removed ) ); 00107 00108 __avahi_thread->watch_service("_fountain._tcp", __avahi_dispatcher); 00109 __avahi_thread->start(); 00110 } 00111 00112 /** Destructor. */ 00113 FuseViewerGtkWindow::~FuseViewerGtkWindow() 00114 { 00115 delete __avahi_thread; 00116 delete __avahi_dispatcher; 00117 } 00118 00119 /** Signal handler called after AvahiThread detects a new NetworkService */ 00120 void 00121 FuseViewerGtkWindow::on_service_added(fawkes::NetworkService* service) 00122 { 00123 const char* name = service->name(); 00124 const char* host = service->host(); 00125 00126 __host_service_map[host] = name; 00127 __img_list_widget->add_fountain_service( 00128 name, 00129 host, 00130 service->port()); 00131 } 00132 00133 /** Signal handler called after AvahiThread detects a NetworkService removal */ 00134 void 00135 FuseViewerGtkWindow::on_service_removed( fawkes::NetworkService* service ) 00136 { 00137 __img_list_widget->remove_fountain_service( service->name() ); 00138 00139 if (__cur_service_name == service->name()) { 00140 close_image(); 00141 } 00142 00143 std::map<std::string, std::string>::const_iterator it = __host_service_map.begin(); 00144 for (; it != __host_service_map.end(); ++it) { 00145 if (__cur_service_name == it->second) { 00146 __host_service_map.erase(it->first); 00147 break; 00148 } 00149 } 00150 } 00151 00152 /** Signal handler that is called when an image is selected in the image list */ 00153 void 00154 FuseViewerGtkWindow::on_fuse_image_selected() 00155 { 00156 __img_list_widget->set_sensitive(Gtk::SENSITIVITY_OFF); 00157 std::string host; 00158 unsigned short port; 00159 std::string image_id; 00160 bool compression; 00161 00162 __img_list_widget->get_selected_image(host, port, image_id, compression); 00163 00164 close_image(); 00165 00166 try { 00167 __cam = new NetworkCamera( host.c_str(), port, image_id.c_str(), compression ); 00168 __cam->open(); 00169 __cam->start(); 00170 __cur_service_name = __host_service_map[host]; 00171 00172 __img_widget = new ImageWidget(__cam, 300); 00173 __image_viewport->add(*__img_widget); 00174 __image_viewport->set_size_request(__cam->pixel_width(), __cam->pixel_height()); 00175 show_all_children(); 00176 __save_type->set_sensitive(Gtk::SENSITIVITY_ON); 00177 00178 set_status(image_id, host, port); 00179 } 00180 catch (Exception& e) { 00181 __cam = NULL; 00182 e.print_trace(); 00183 } 00184 00185 __img_list_widget->set_sensitive(Gtk::SENSITIVITY_ON); 00186 } 00187 00188 /** Signal handler that is called if the 'Auto save' checkbox status changes */ 00189 void 00190 FuseViewerGtkWindow::on_auto_save_cbt_change() 00191 { 00192 if (__auto_save->get_active()) { 00193 __save_btn->set_sensitive(false); 00194 00195 __img_widget->save_on_refresh_cam(true, 00196 __save_filechooser->get_current_folder(), 00197 __save_type->get_active_text(), 00198 __img_num); 00199 } 00200 else { 00201 __img_widget->save_on_refresh_cam(false); 00202 __img_num = __img_widget->get_image_num(); 00203 00204 __save_btn->set_sensitive(true); 00205 } 00206 } 00207 00208 /** Signal handler that is called when the fileformat to save images changes */ 00209 void 00210 FuseViewerGtkWindow::on_save_type_change() 00211 { 00212 if (__save_type->get_active_row_number()) { 00213 __auto_save->set_sensitive(true); 00214 00215 if (__auto_save->get_active()) __img_num = __img_widget->get_image_num(); 00216 on_auto_save_cbt_change(); 00217 } 00218 else { 00219 __auto_save->set_active(false); 00220 __auto_save->set_sensitive(false); 00221 __save_btn->set_sensitive(false); 00222 } 00223 } 00224 00225 /** Signal handler that is called when the 'Save image' button is pressed */ 00226 void 00227 FuseViewerGtkWindow::on_save_image_clicked() 00228 { 00229 char *ctmp; 00230 if (asprintf(&ctmp, "%s/%06u.%s", __save_filechooser->get_current_folder().c_str(), 00231 ++__img_num, __save_type->get_active_text().c_str()) != -1) { 00232 Glib::ustring fn = ctmp; 00233 free(ctmp); 00234 00235 __img_widget->save_image(fn, __save_type->get_active_text()); 00236 } else { 00237 printf("Could not save file, asprintf() ran out of memory"); 00238 } 00239 } 00240 00241 /** 00242 * Sets the current status (to the statusbar) 00243 * @param img_id the id of the current selected image 00244 * @param host the host that provides the image 00245 * @param port the port to transfer the image 00246 */ 00247 void 00248 FuseViewerGtkWindow::set_status(std::string img_id, std::string host, unsigned short port) 00249 { 00250 if (!img_id.length()) { 00251 __statusbar->push(Glib::ustring("Not connected.")); 00252 } 00253 else { 00254 char *ctmp = NULL; 00255 if (asprintf(&ctmp, "Host: %s:%u\tId: %s", 00256 host.c_str(), port, img_id.c_str())) { 00257 __statusbar->push(Glib::ustring(ctmp)); 00258 free(ctmp); 00259 } 00260 } 00261 } 00262 00263 /** Closes the image and the camera */ 00264 void 00265 FuseViewerGtkWindow::close_image() 00266 { 00267 if (__img_widget) { 00268 __image_viewport->remove(); 00269 delete __img_widget; 00270 __img_widget = NULL; 00271 __save_type->set_sensitive(Gtk::SENSITIVITY_OFF); 00272 } 00273 00274 if (__cam) { 00275 __cam->stop(); 00276 __cam->close(); 00277 delete __cam; 00278 __cam = NULL; 00279 } 00280 00281 set_status(""); 00282 } 00283