fuse_viewer_gui.cpp

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 

Generated on Tue Feb 22 13:32:17 2011 for Fawkes API by  doxygen 1.4.7