00001 /* --------------------------------------------------------------------------- 00002 Phission : 00003 Realtime Vision Processing System 00004 00005 Copyright (C) 2003-2006 Philip D.S. Thoren (pthoren@cs.uml.edu) 00006 University of Massachusetts at Lowell, 00007 Laboratory for Artificial Intelligence and Robotics 00008 00009 This file is part of Phission. 00010 00011 Phission is free software; you can redistribute it and/or modify 00012 it under the terms of the GNU Lesser General Public License as published by 00013 the Free Software Foundation; either version 2 of the License, or 00014 (at your option) any later version. 00015 00016 Phission is distributed in the hope that it will be useful, 00017 but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 GNU Lesser General Public License for more details. 00020 00021 You should have received a copy of the GNU Lesser General Public License 00022 along with Phission; if not, write to the Free Software 00023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00024 00025 ---------------------------------------------------------------------------*/ 00026 #ifdef HAVE_CONFIG_H 00027 #include <phissionconfig.h> 00028 #endif 00029 00030 #include <phStandard.h> 00031 00032 #include <phFLImageWindow.h> 00033 00034 #include <phError.h> 00035 #include <phMemory.h> 00036 #include <phPrint.h> 00037 00038 /* ---------------------------------------------------------------------- */ 00039 static void on_close_window(Fl_Widget *widget, void *ptr) 00040 { 00041 phFUNCTION("on_close_window") 00042 00043 phFLImageWindow *fl_window = (phFLImageWindow *)widget; 00044 00045 fl_window->user_close(ptr); 00046 } 00047 00048 /* ---------------------------------------------------------------------- */ 00049 phFLImageWindow::phFLImageWindow( int32_t x, int32_t y, 00050 uint32_t w, uint32_t h, 00051 char *title, 00052 uint32_t flags ) : 00053 Fl_Double_Window(0,0,w,h,title), 00054 phImageWindow(x,y,w,h,title,flags ) 00055 { 00056 phFUNCTION("phFLImageWindow::phFLImageWindow") 00057 00058 /* 00059 uint32_t max_width = 0; 00060 uint32_t max_height = 0; 00061 */ 00062 rc = this->lock(); 00063 phPRINT_RC(rc,NULL,"this->lock() failed."); 00064 00065 this->m_redraw = 0; 00066 this->m_exit_now = 0; 00067 00068 this->size_range( this->m_min_width, this->m_min_height, 00069 36000, 24000 ); 00070 00071 this->Fl_Double_Window::callback(on_close_window, 00072 (void *)&this->m_exit_now); 00073 rc = Fl::visual(FL_DOUBLE|FL_INDEX|FL_RGB); 00074 00075 this->m_formats = phImageRGB24 | phImageRGBA32 | phImageGREY8; 00076 00077 rc = this->unlock(); 00078 phPRINT_RC(rc,NULL,"this->unlock() failed."); 00079 } 00080 00081 /* ---------------------------------------------------------------------- */ 00082 phFLImageWindow::~phFLImageWindow() 00083 { 00084 phFUNCTION("phFLImageWindow::~phFLImageWindow") 00085 00086 int locked = 0; 00087 00088 phTHIS_LOCK(locked); 00089 error: 00090 return; 00091 } 00092 00093 /* ---------------------------------------------------------------------- */ 00094 int phFLImageWindow::private_show( ) 00095 { 00096 /* phFUNCTION("phFLImageWindow::private_show") */ 00097 /* 00098 * We are locked when we get into a "private" method; Locking is done 00099 * as a policy in any public interface method that calls a private 00100 * (implementation specific) method 00101 int locked = 1; 00102 */ 00103 00104 this->Fl_Double_Window::show(); 00105 00106 return phSUCCESS; 00107 } 00108 00109 /* ---------------------------------------------------------------------- */ 00110 int phFLImageWindow::private_hide( ) 00111 { 00112 /*phFUNCTION("phFLImageWindow::private_hide")*/ 00113 /* 00114 * We are locked when we get into a "private" method; Locking is done 00115 * as a policy in any public interface method that calls a private 00116 * (implementation specific) method 00117 int locked = 1; 00118 */ 00119 00120 this->Fl_Double_Window::hide(); 00121 00122 return phSUCCESS; 00123 } 00124 00125 /* ---------------------------------------------------------------------- */ 00126 int phFLImageWindow::private_update() 00127 { 00128 phFUNCTION("phFLImageWindow::update") 00129 /* 00130 * We are locked when we get into a "private" method; Locking is done 00131 * as a policy in any public interface method that calls a private 00132 * (implementation specific) method 00133 int locked = 1; 00134 */ 00135 int writeLocked = 0; 00136 00137 rc = this->m_image.writeLock(); 00138 phCHECK_RC(rc,NULL,"this->m_image.writeLock() failed."); 00139 writeLocked = 1; 00140 00141 if (!this->m_image.isNull()) 00142 { 00143 /* if we need to redraw, then redraw */ 00144 this->private_redraw(); 00145 } 00146 00147 rc = this->m_image.rwUnlock(); 00148 writeLocked = 0; 00149 phCHECK_RC(rc,NULL,"this->m_image.rwUnlock() failed."); 00150 00151 return phSUCCESS; 00152 00153 error: 00154 if (writeLocked) 00155 { 00156 rc = this->m_image.rwUnlock(); 00157 phPRINT_RC(rc,NULL,"this->m_image.rwUnlock() failed."); 00158 writeLocked = 0; 00159 } 00160 00161 return phFAIL; 00162 } 00163 00164 /* ---------------------------------------------------------------------- */ 00165 void phFLImageWindow::draw() 00166 { 00167 phFUNCTION("phFLImageWindow::draw") 00168 uint8_t *img = NULL; 00169 #if defined(WIN32) 00170 int x = 0; 00171 int y = 0; 00172 #endif 00173 int locked = 0; 00174 int writeLocked = 0; 00175 /* 00176 * This is for RGB 00177 * void fl_draw_image(const uchar *, int X, int Y, 00178 * int W, int H, int D = 3, int LD = 0) 00179 * 00180 * This is for Greyscale 00181 * void fl_draw_image_mono(const uchar *, int X, int Y, 00182 * int W, int H, int D = 1, int LD = 0) 00183 */ 00184 00185 phTHIS_LOCK(locked); 00186 00187 if (this->m_redraw == 0) 00188 { 00189 DEBUG_PRINT("FLTK called draw\n"); 00190 goto error; 00191 } 00192 00193 #if 0 00194 /* This is here because phDisplayInterface locks the local m_image 00195 * and could potentially deadlock. We only want to redraw if we're 00196 * explicitly told to by phDisplayInterface so the check above 00197 * for m_redraw should prevent a dead lock. This is commented out 00198 * as a reminder of the situation. */ 00199 rc = this->m_image.tryWriteLock(); 00200 if (rc == 1) 00201 { 00202 DEBUG_PRINT("Failed redraw\n"); 00203 goto error; 00204 } 00205 phCHECK_RC(rc,NULL,"this->m_image.tryWriteLock() failed."); 00206 #else 00207 rc = this->m_image.writeLock(); 00208 phCHECK_RC(rc,NULL,"this->m_image.writeLock() failed."); 00209 00210 #endif 00211 writeLocked = 1; 00212 00213 if (!this->m_image.isNull()) 00214 { 00215 rc = this->m_image.convert( this->getFormats(),phImageRGB24); 00216 phPRINT_RC(rc,NULL,"m_image.convert();"); 00217 00218 if (this->m_image.getFormat() & this->getFormats()) 00219 { 00220 int depth = 0; 00221 00222 this->m_image.resize(this->phImageWindow::m_w,this->phImageWindow::m_h); 00223 00224 /* Try to remove any special flags */ 00225 /* The format will be one of the following after 00226 * the convert call above */ 00227 switch (this->m_image.getFormat()) 00228 { 00229 case phImageRGB24: 00230 depth = 24; 00231 break; 00232 case phImageRGBA32: 00233 depth = 32; 00234 break; 00235 case phImageGREY8: 00236 depth = 8; 00237 break; 00238 default: 00239 rc = this->m_image.convert(phImageRGB24); 00240 if (rc != 0) 00241 /* depth = 0 will prevent the image from being drawn */ 00242 depth = 0; 00243 else 00244 depth = 24; 00245 break; 00246 }; 00247 00248 img = (uint8_t *)this->m_image.getData(); 00249 00250 if (img == NULL) goto error; 00251 00252 #if defined(WIN32) 00253 x=this->x(); 00254 y=this->y(); 00255 #endif 00256 00257 if (depth > 16) 00258 { 00259 fl_draw_image(img, 00260 0,0, 00261 this->m_image.getWidth(), 00262 this->m_image.getHeight(), 00263 depth / 8); 00264 } 00265 else if (depth > 0) 00266 { 00267 fl_draw_image_mono(img, 00268 0,0, 00269 this->m_image.getWidth(), 00270 this->m_image.getHeight(), 00271 depth / 8); 00272 } 00273 00274 /* maintain frames-per-second */ 00275 this->tickFrame(); 00276 } 00277 /* else if (this->m_image.getFormat() & ImageYUV) { } */ 00278 } 00279 error: 00280 if (this->m_redraw > 0) this->m_redraw = 0; 00281 00282 if (writeLocked) 00283 { 00284 rc = this->m_image.rwUnlock(); 00285 phPRINT_RC(rc,NULL,"this->m_image.rwUnlock() failed."); 00286 writeLocked = 0; 00287 } 00288 00289 phTHIS_ERROR_UNLOCK(locked); 00290 00291 return; 00292 } 00293 00294 /* ---------------------------------------------------------------------- */ 00295 int phFLImageWindow::private_redraw() 00296 { 00297 phFUNCTION("phFLImageWindow::private_redraw") 00298 /* 00299 * We are locked when we get into a "private" method; Locking is done 00300 * as a policy in any public interface method that calls a private 00301 * (implementation specific) method 00302 int locked = 1; 00303 */ 00304 00305 this->m_redraw = 1; 00306 this->draw(); 00307 00308 return phSUCCESS; 00309 } 00310 00311 /* ---------------------------------------------------------------------- */ 00312 void phFLImageWindow::resize( int x, int y, int w, int h ) 00313 { 00314 phFUNCTION("phFLImageWindow::resize") 00315 int locked = 0; 00316 uint32_t lw = w; 00317 uint32_t lh = h; 00318 00319 if ((w <= 0) || h <= 0) return; 00320 00321 phTHIS_LOCK(locked); 00322 00323 if ((lh != this->phImageWindow::m_h) || 00324 (lw != this->phImageWindow::m_w) || 00325 (x != this->phImageWindow::m_x) || 00326 (y != this->phImageWindow::m_y)) 00327 { 00328 this->phImageWindow::m_x = x; 00329 this->phImageWindow::m_y = y; 00330 this->phImageWindow::m_w = lw; 00331 this->phImageWindow::m_h = lh; 00332 00333 Fl_Double_Window::resize(this->phImageWindow::m_x,this->phImageWindow::m_y, 00334 this->phImageWindow::m_w,this->phImageWindow::m_h); 00335 } 00336 00337 phTHIS_UNLOCK(locked); 00338 00339 return; 00340 error: 00341 phTHIS_ERROR_UNLOCK(locked); 00342 00343 return; 00344 } 00345 00346 /* ---------------------------------------------------------------------- */ 00347 int phFLImageWindow::private_resize( uint32_t w, uint32_t h) 00348 { 00349 phFUNCTION("phFLImageWindow::private_resize") 00350 /* 00351 * We are locked when we get into a "private" method; Locking is done 00352 * as a policy in any public interface method that calls a private 00353 * (implementation specific) method 00354 int locked = 1; 00355 */ 00356 00357 if ((h != this->phImageWindow::m_h) || (w != this->phImageWindow::m_w)) 00358 { 00359 this->phImageWindow::m_w = w; 00360 this->phImageWindow::m_h = h; 00361 00362 Fl_Double_Window::resize(this->phImageWindow::m_x,this->phImageWindow::m_y, 00363 this->phImageWindow::m_w,this->phImageWindow::m_h); 00364 } 00365 00366 return phSUCCESS; 00367 } 00368 00369 /* ---------------------------------------------------------------------- */ 00370 int phFLImageWindow::private_move( int32_t x, int32_t y) 00371 { 00372 phFUNCTION("phFLImageWindow::private_move") 00373 /* 00374 * We are locked when we get into a "private" method; Locking is done 00375 * as a policy in any public interface method that calls a private 00376 * (implementation specific) method 00377 int locked = 1; 00378 */ 00379 00380 if ((x != this->phImageWindow::m_x) || (y != this->phImageWindow::m_y)) 00381 { 00382 this->phImageWindow::m_x = x; 00383 this->phImageWindow::m_y = y; 00384 00385 Fl_Double_Window::resize(this->phImageWindow::m_x,this->phImageWindow::m_y, 00386 this->phImageWindow::m_w,this->phImageWindow::m_h); 00387 } 00388 00389 return phSUCCESS; 00390 } 00391 00392 /* ---------------------------------------------------------------------- */ 00393 int phFLImageWindow::private_minsize( uint32_t min_w, uint32_t min_h) 00394 { 00395 phFUNCTION("phFLImageWindow::private_minsize") 00396 /* 00397 * We are locked when we get into a "private" method; Locking is done 00398 * as a policy in any public interface method that calls a private 00399 * (implementation specific) method 00400 int locked = 1; 00401 */ 00402 00403 this->size_range( min_w, min_h, 36000, 24000 ); 00404 00405 return phSUCCESS; 00406 } 00407 00408 /* ---------------------------------------------------------------------- */ 00409 void phFLImageWindow::user_close(void *ptr) 00410 { 00411 phFUNCTION("phFLImageWindow::user_close") 00412 volatile int *exit_now = (volatile int *)ptr; 00413 int locked = 0; 00414 00415 phTHIS_LOCK(locked); 00416 00417 if (this->isOpen()) 00418 { 00419 this->hide(); 00420 00421 if (exit_now != NULL) 00422 { 00423 *exit_now = 1; 00424 } 00425 00426 rc = this->m_image.wakeup_self(); 00427 phPRINT_RC(rc,NULL,"this->m_image.wakeup_self() failed."); 00428 00429 phTHIS_UNLOCK(locked); 00430 00431 Fl::atclose(this, ptr); 00432 } 00433 else 00434 { 00435 phTHIS_UNLOCK(locked); 00436 } 00437 return; 00438 error: 00439 phTHIS_ERROR_UNLOCK(locked); 00440 return; 00441 } 00442 00443 /* ---------------------------------------------------------------------- */ 00444 int phFLImageWindow::isOpen() 00445 { 00446 return this->isRunning(); 00447 } 00448 00449 /* ---------------------------------------------------------------------- */ 00450 int phFLImageWindow::handle(int event) 00451 { 00452 switch(event) { 00453 case FL_KEYDOWN: 00454 if (Fl::event_key() == 'q') 00455 { 00456 this->user_close((void *)&this->m_exit_now); 00457 return 1; 00458 } 00459 else 00460 { 00461 return Fl_Widget::handle(event); 00462 } 00463 00464 break; 00465 default: 00466 return Fl_Widget::handle(event); 00467 } 00468 00469 return 0; 00470 } 00471 00472 /* ---------------------------------------------------------------------- */ 00473 int phFLImageWindow::setup() 00474 { 00475 phFUNCTION("phFLImageWindow::setup") 00476 00477 this->m_exit_now = 0; 00478 00479 return phSUCCESS; 00480 } 00481 00482 /* ---------------------------------------------------------------------- */ 00483 int phFLImageWindow::wakeup() 00484 { 00485 phFUNCTION("phFLImageWindow::wakeup") 00486 00487 this->m_image.wakeup_self(); 00488 00489 return phSUCCESS; 00490 } 00491 00492 /* ---------------------------------------------------------------------- */ 00493 int phFLImageWindow::run() 00494 { 00495 phFUNCTION("phFLImageWindow::run") 00496 00497 DEBUG_PRINT("Thread started\n"); 00498 00499 this->phImageWindow::show(); 00500 00501 rc = this->signal_running(); 00502 phCHECK_RC(rc,NULL,"this->signal_running()"); 00503 00504 while ((this->isRunning()) && (this->m_exit_now == 0)) 00505 { 00506 /* Handle GUI EVENTS */ 00507 #define LOCKEM() 1 00508 /* Must lock, otherwise, the Fl::check() could collide with another 00509 * function call and cause the "unexpected async reply" on X systems 00510 */ 00511 #if 1 00512 #if LOCKEM() 00513 rc = this->lock(); 00514 phPRINT_RC(rc,NULL,"fl_window->lock() failed."); 00515 #endif 00516 00517 rc = Fl::check(); 00518 00519 #if LOCKEM() 00520 rc = this->unlock(); 00521 phPRINT_RC(rc,NULL,"fl_window->unlock() failed."); 00522 #endif 00523 00524 #if 0 00525 phYield(); 00526 #else 00527 phMSleep(0); 00528 #endif 00529 #else 00530 /* Still no way to wake up a blocked window from this */ 00531 rc = Fl::wait(); 00532 #endif 00533 } 00534 00535 this->hide(); 00536 00537 DEBUG_PRINT("Thread returning with success\n"); 00538 00539 return phSUCCESS; 00540 error: 00541 phPROGRESS("Thread returning with error\n"); 00542 00543 rc = this->signal_error(); 00544 phPRINT_RC(rc,NULL,"this->signal_error()"); 00545 00546 this->hide(); 00547 00548 return phFAIL; 00549 00550 } 00551 00552 void phFLImageWindow::hide() 00553 { 00554 this->phImageWindow::hide(); 00555 } 00556
Copyright (C) 2002 - 2007 |
Philip D.S. Thoren ( pthoren@users.sourceforge.net ) University Of Massachusetts at Lowell Robotics Lab |