23 #include "fuse_image_list_widget.h"
25 #include <fvutils/net/fuse_imagelist_content.h>
26 #include <fvutils/net/fuse_message.h>
27 #include <netinet/in.h>
34 namespace firevision {
43 FuseImageListWidget::FuseImageListWidget()
45 m_chk_compression = NULL;
46 m_chk_auto_update = NULL;
48 m_cur_client.active =
false;
50 m_new_clients.clear();
51 m_delete_clients.clear();
53 m_image_list = Gtk::TreeStore::create(m_image_record);
55 m_signal_get_image_list.connect(sigc::mem_fun(*
this, &FuseImageListWidget::get_image_list));
56 m_signal_delete_clients.connect(sigc::mem_fun(*
this, &FuseImageListWidget::delete_clients));
57 m_signal_update_image_l.connect(sigc::mem_fun(*
this, &FuseImageListWidget::update_image_list));
59 #if GTK_VERSION_LT(3, 0)
60 m_popup_menu = Gtk::manage(
new Gtk::Menu());
61 Gtk::Menu::MenuList &menulist = m_popup_menu->items();
63 Gtk::Menu_Helpers::MenuElem(
"Update now",
64 sigc::mem_fun(*
this, &FuseImageListWidget::update_image_list)));
65 menulist.push_back(Gtk::Menu_Helpers::SeparatorElem());
67 Gtk::Menu_Helpers::MenuElem(
"Add host manually",
68 sigc::mem_fun(*
this, &FuseImageListWidget::on_add_host_manually)));
71 set_image_list_trv(
this);
75 FuseImageListWidget::~FuseImageListWidget()
79 while (m_new_clients.size() != 0) {
80 c = m_new_clients.front().client;
81 m_new_clients.pop_front();
87 m_new_clients.unlock();
89 if (m_cur_client.active) {
90 m_cur_client.active =
false;
91 m_delete_clients.push_locked(m_cur_client.client);
102 FuseImageListWidget::add_fountain_service(
const char *name,
const char *host_name, uint32_t port)
105 m_img_list_mutex.lock();
106 Gtk::TreeModel::Children children = m_image_list->children();
107 for (Gtk::TreeModel::Children::iterator iter = children.begin(); iter != children.end(); ++iter) {
108 Gtk::TreeModel::Row row = *iter;
109 if (row[m_image_record.service_name] == Glib::ustring(name)) {
110 m_img_list_mutex.unlock();
114 m_img_list_mutex.unlock();
117 m_new_clients.lock();
120 if (name == iter->service_name) {
121 m_new_clients.unlock();
125 m_new_clients.unlock();
129 data.service_name = std::string(name);
130 data.host_name = std::string(host_name);
134 m_new_clients.push_back_locked(data);
135 m_signal_get_image_list();
142 FuseImageListWidget::remove_fountain_service(
const char *name)
144 m_img_list_mutex.lock();
145 Gtk::TreeModel::Children children = m_image_list->children();
146 Gtk::TreeModel::Children::iterator iter = children.begin();
147 while (iter != children.end()) {
148 Gtk::TreeModel::Row row = *iter;
149 if (row[m_image_record.service_name] == Glib::ustring(name)) {
150 iter = m_image_list->erase(iter);
151 m_image_list->row_deleted(m_image_list->get_path(iter));
156 m_img_list_mutex.unlock();
163 FuseImageListWidget::set_image_list_trv(Gtk::TreeView *trv)
165 m_img_list_mutex.lock();
166 m_trv_image_list = trv;
167 m_trv_image_list->set_model(m_image_list);
168 m_trv_image_list->append_column(
"asdf", m_image_record.display_text);
169 m_trv_image_list->set_headers_visible(
false);
170 m_trv_image_list->signal_event().connect(
171 sigc::mem_fun(*
this, &FuseImageListWidget::on_image_event));
172 m_trv_image_list->signal_cursor_changed().connect(
173 sigc::mem_fun(*
this, &FuseImageListWidget::on_image_selected));
174 m_img_list_mutex.unlock();
181 FuseImageListWidget::set_toggle_compression_chk(Gtk::CheckButton *chk)
183 m_chk_compression = chk;
184 m_chk_compression->signal_toggled().connect(
185 sigc::mem_fun(*
this, &FuseImageListWidget::on_compression_toggled));
192 FuseImageListWidget::set_auto_update_chk(Gtk::CheckButton *chk)
194 m_chk_auto_update = chk;
195 m_chk_auto_update->signal_toggled().connect(
196 sigc::mem_fun(*
this, &FuseImageListWidget::on_auto_update_toggled));
205 FuseImageListWidget::image_selected()
207 return m_signal_image_selected;
214 FuseImageListWidget::auto_update()
216 return m_auto_update;
224 FuseImageListWidget::set_auto_update(
bool active,
unsigned int interval_sec)
226 m_auto_update = active;
227 m_interval_sec = interval_sec;
230 #if GLIBMM_MAJOR_VERSION > 2 || (GLIBMM_MAJOR_VERSION == 2 && GLIBMM_MINOR_VERSION >= 14)
231 m_timeout_conn = Glib::signal_timeout().connect_seconds(
232 sigc::mem_fun(*
this, &FuseImageListWidget::on_update_timeout), m_interval_sec);
235 Glib::signal_timeout().connect(sigc::mem_fun(*
this, &FuseImageListWidget::on_update_timeout),
239 m_timeout_conn.disconnect();
250 FuseImageListWidget::get_selected_image(std::string & host_name,
251 unsigned short &port,
252 std::string & image_id,
255 if (!m_trv_image_list) {
259 m_img_list_mutex.lock();
260 Glib::RefPtr<Gtk::TreeSelection> selection = m_trv_image_list->get_selection();
262 if (selection->count_selected_rows() != 1) {
263 m_img_list_mutex.unlock();
267 Gtk::TreeModel::iterator iter = selection->get_selected();
268 host_name = iter->get_value(m_image_record.host_name);
269 port = iter->get_value(m_image_record.port);
270 image_id = iter->get_value(m_image_record.image_id);
271 m_img_list_mutex.unlock();
273 if (m_chk_compression) {
274 compression = m_chk_compression->get_active();
283 FuseImageListWidget::on_image_event(GdkEvent *event)
285 GdkEventButton btn =
event->button;
286 if (btn.type == GDK_BUTTON_PRESS && btn.button == 3) {
287 #if GTK_VERSION_LT(3, 0)
288 m_popup_menu->popup(btn.button, btn.time);
296 FuseImageListWidget::on_image_selected()
298 m_img_list_mutex.lock();
299 Glib::RefPtr<Gtk::TreeSelection> selection = m_trv_image_list->get_selection();
301 Gtk::TreeModel::iterator iter = selection->get_selected();
302 Glib::ustring image_id;
303 image_id = (*iter)[m_image_record.image_id];
304 m_img_list_mutex.unlock();
306 if ((image_id != m_cur_image_id) && (image_id !=
"invalid")) {
307 m_cur_image_id = image_id;
308 m_signal_image_selected();
313 FuseImageListWidget::on_auto_update_toggled()
315 set_auto_update(m_chk_auto_update->get_active());
319 FuseImageListWidget::on_compression_toggled()
321 m_signal_image_selected();
325 FuseImageListWidget::get_image_list()
327 if (m_cur_client.active)
333 m_new_clients.lock();
334 if (m_new_clients.size() == 0) {
336 #if GLIBMM_MAJOR_VERSION > 2 || (GLIBMM_MAJOR_VERSION == 2 && GLIBMM_MINOR_VERSION >= 14)
337 m_timeout_conn = Glib::signal_timeout().connect_seconds(
338 sigc::mem_fun(*
this, &FuseImageListWidget::on_update_timeout), m_interval_sec);
340 m_timeout_conn = Glib::signal_timeout().connect(
341 sigc::mem_fun(*
this, &FuseImageListWidget::on_update_timeout), m_interval_sec);
344 m_new_clients.unlock();
348 m_cur_client = m_new_clients.front();
349 m_cur_client.active =
true;
350 m_new_clients.pop_front();
351 m_new_clients.unlock();
354 m_cur_client.client =
new FuseClient(m_cur_client.host_name.c_str(), m_cur_client.port,
this);
355 m_cur_client.client->connect();
356 m_cur_client.client->start();
357 m_cur_client.client->enqueue(FUSE_MT_GET_IMAGE_LIST);
360 m_cur_client.client->cancel();
361 m_cur_client.client->join();
362 delete m_cur_client.client;
363 m_cur_client.active =
false;
368 FuseImageListWidget::delete_clients()
372 m_delete_clients.lock();
373 while (m_delete_clients.size() != 0) {
374 c = m_delete_clients.front();
375 m_delete_clients.pop();
382 m_delete_clients.unlock();
386 FuseImageListWidget::on_update_timeout()
388 m_signal_update_image_l();
389 return m_auto_update;
393 FuseImageListWidget::update_image_list()
395 m_timeout_conn.disconnect();
396 if (m_img_list_mutex.try_lock()) {
397 Gtk::TreeModel::Children children = m_image_list->children();
398 for (Gtk::TreeModel::Children::iterator iter = children.begin(); iter != children.end();
400 if ((*iter)[m_image_record.image_id] ==
"invalid") {
403 Glib::ustring service_name = (*iter)[m_image_record.service_name];
404 Glib::ustring host_name = (*iter)[m_image_record.host_name];
405 data.service_name = std::string(service_name.c_str());
406 data.host_name = std::string(host_name.c_str());
407 data.port = (*iter)[m_image_record.port];
410 m_new_clients.push_back_locked(data);
413 m_img_list_mutex.unlock();
416 m_signal_get_image_list();
420 FuseImageListWidget::fuse_invalid_server_version(uint32_t local_version,
421 uint32_t remote_version)
throw()
423 printf(
"Invalid versions: local: %u remote: %u\n", local_version, remote_version);
427 FuseImageListWidget::fuse_connection_established() throw()
432 FuseImageListWidget::fuse_connection_died() throw()
434 if (m_cur_client.active) {
435 m_delete_clients.push_locked(m_cur_client.client);
436 m_cur_client.active =
false;
439 m_signal_delete_clients();
446 case FUSE_MT_IMAGE_LIST: {
448 m_img_list_mutex.lock();
449 Gtk::TreeModel::Children children = m_image_list->children();
450 Gtk::TreeModel::Children::iterator iter = children.begin();
451 while (iter != children.end()) {
452 Gtk::TreeModel::Row row = *iter;
453 if (row[m_image_record.service_name] == Glib::ustring(m_cur_client.service_name)) {
454 iter = m_image_list->erase(iter);
463 Gtk::TreeModel::Row row = *m_image_list->append();
464 row[m_image_record.display_text] = Glib::ustring(m_cur_client.host_name);
465 row[m_image_record.service_name] = Glib::ustring(m_cur_client.service_name);
466 row[m_image_record.host_name] = Glib::ustring(m_cur_client.host_name);
467 row[m_image_record.port] = m_cur_client.port;
468 row[m_image_record.colorspace] = 0;
469 row[m_image_record.image_id] =
"invalid";
470 row[m_image_record.width] = 0;
471 row[m_image_record.height] = 0;
472 row[m_image_record.buffer_size] = 0;
474 Gtk::TreeModel::Path path = m_image_list->get_path(row);
478 char image_id[IMAGE_ID_MAX_LENGTH + 1];
479 image_id[IMAGE_ID_MAX_LENGTH] =
'\0';
480 strncpy(image_id, image_info->
image_id, IMAGE_ID_MAX_LENGTH);
482 Gtk::TreeModel::Row childrow = *m_image_list->append(row.children());
483 childrow[m_image_record.display_text] = Glib::ustring(image_id);
484 childrow[m_image_record.service_name] = Glib::ustring(m_cur_client.service_name);
485 childrow[m_image_record.host_name] = Glib::ustring(m_cur_client.host_name);
486 childrow[m_image_record.port] = m_cur_client.port;
487 childrow[m_image_record.colorspace] = ntohl(image_info->
colorspace);
488 childrow[m_image_record.image_id] = Glib::ustring(image_id);
489 childrow[m_image_record.width] = ntohl(image_info->
width);
490 childrow[m_image_record.height] = ntohl(image_info->
height);
491 childrow[m_image_record.buffer_size] = ntohl(image_info->
buffer_size);
494 m_trv_image_list->expand_row(path,
false);
502 m_img_list_mutex.unlock();
504 m_delete_clients.push_locked(m_cur_client.client);
505 m_cur_client.active =
false;
507 m_signal_get_image_list();
508 m_signal_delete_clients();
513 default: printf(
"Unhandled message type\n");
518 FuseImageListWidget::on_add_host_manually()
520 Gtk::Dialog *add_host =
new Gtk::Dialog(
"Add host manually",
true);
521 add_host->add_button(Gtk::Stock::ADD, Gtk::RESPONSE_OK);
522 add_host->add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
524 Gtk::Table *tab = Gtk::manage(
new Gtk::Table(2, 2,
false));
525 Gtk::Label *hlab = Gtk::manage(
new Gtk::Label(
"Host:"));
526 Gtk::Label *plab = Gtk::manage(
new Gtk::Label(
"Port:"));
527 Gtk::Entry *hent = Gtk::manage(
new Gtk::Entry());
528 Gtk::HBox * pbox = Gtk::manage(
new Gtk::HBox());
530 #if GTK_VERSION_GE(3, 0)
531 Glib::RefPtr<Gtk::Adjustment> prange = Gtk::Adjustment::create(2208, 1, 65535);
533 Gtk::Adjustment prange(2208, 1, 65535);
535 Gtk::SpinButton *pent = Gtk::manage(
new Gtk::SpinButton(prange));
537 char *fawkes_ip = getenv(
"FAWKES_IP");
539 hent->set_text(std::string(fawkes_ip).append(
":2208"));
541 hent->set_text(
"localhost:2208");
543 pbox->pack_start(*pent,
false,
false, 0);
544 tab->attach(*hlab, 1, 2, 1, 2);
545 tab->attach(*plab, 1, 2, 2, 3);
546 tab->attach(*hent, 2, 3, 1, 2);
547 tab->attach(*pbox, 2, 3, 2, 3);
549 add_host->get_vbox()->pack_start(*tab,
false,
true, 0);
550 add_host->get_vbox()->show_all_children(
true);
552 if (add_host->run() == Gtk::RESPONSE_OK) {
553 std::string name =
"fountain on ";
554 std::string host = hent->get_text();
555 unsigned short port = 2208;
557 Glib::ustring::size_type pos;
558 if ((pos = host.find(
':')) != Glib::ustring::npos) {
559 Glib::ustring tmp_host =
"";
560 unsigned int tmp_port = 1234567;
561 std::istringstream is(host.replace(pos, 1,
" "));
565 if (tmp_port != 1234567 && tmp_host.size()) {
572 add_fountain_service(name.c_str(), host.c_str(), port);
Base class for exceptions in Fawkes.
void print_trace()
Prints trace to stderr.
void join()
Join the thread.
void cancel()
Cancel a thread.
void disconnect()
Disconnect.
bool has_next()
Check if another image info is available.
FUSE_imageinfo_t * next()
Get next image info.
Fawkes library namespace.
uint32_t colorspace
color space
uint32_t height
height in pixels
uint32_t width
width in pixels
char image_id[IMAGE_ID_MAX_LENGTH]
image ID
uint32_t buffer_size
size of following image buffer in bytes