diff --git a/image_view_module/CMakeLists.txt b/image_view_module/CMakeLists.txt index 39d2fe8..806fb3d 100644 --- a/image_view_module/CMakeLists.txt +++ b/image_view_module/CMakeLists.txt @@ -1,136 +1,151 @@ -cmake_minimum_required(VERSION 2.8) +# RUN cmake -DSTANDALONE=1 for standalone example +# -DEBUG=1 for debugging +# -DNOGETTEXT=1 for compilation without gettext support +# +# Into cmake file in parent directory add this: +#~ add_subdirectory(image_view_module) +#~ if(IMAGEVIEW_FOUND) + #~ message("Found OpenGL. Will use ${IMLIB} to show data") + #~ target_link_libraries(${PROJ} ${${PROJ}_LIBRARIES} -lm ${IMLIB}) + #~ add_definitions(-DIMAGEVIEW) +#~ else() + #~ message("not found image view module") + #~ target_link_libraries(${PROJ} ${${PROJ}_LIBRARIES} -lm) +#~ endif() -# cmake -DEBUG=1 -> debugging -if(DEFINED EBUG) - add_definitions(-DEBUG) - set(CMAKE_VERBOSE_MAKEFILE ON) +cmake_minimum_required(VERSION 2.8) +set(IMLIB image_view_module) + +if(DEFINED STANDALONE) + set(PROJ ${IMLIB}) + project(${PROJ}) endif() -set(PROJ openglview) -set(MINOR_VERSION "1") -set(MID_VERSION "0") -set(MAJOR_VERSION "0") -set(VERSION "${MAJOR_VERSION}.${MID_VERSION}.${MINOR_VERSION}") - -message("VER: ${VERSION}") - -# default flags set(CFLAGS -O2 -Wextra -Wall -Werror -W -std=gnu99) - set(CMAKE_COLOR_MAKEFILE ON) -# here is one of two variants: all .c in directory or .c files in list -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} SOURCES) -#set(SOURCES list_of_c_files) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} IMSOURCES) -# we can change file list -#if(NOT DEFINED something) -# set(SOURCES ${SOURCES} one_more_list) -# add_definitions(-DSOME_DEFS) -#endif() - -set(MODULES) -# additional modules on condition -#if(DEFINED SOMETHING) -# set(MODULES ${MODULES} more_modules>=version) -# add_definitions(-DSOMEDEFS) -#endif() - -project(${PROJ}) -# change wrong behaviour with install prefix -if(CMAKE_INSTALL_PREFIX MATCHES "/usr/local") - message("Change default install path to /usr") - set(CMAKE_INSTALL_PREFIX "/usr") -endif() -message("Install dir prefix: ${CMAKE_INSTALL_PREFIX}") - -if(NOT DEFINED NOGETTEXT) -# directory should contain dir locale/ru for gettext translations - set(LCPATH ${CMAKE_SOURCE_DIR}/locale/ru) - if(NOT DEFINED LOCALEDIR) - if(DEFINED DEBUG) - set(LOCALEDIR ${CMAKE_CURRENT_SOURCE_DIR}/locale) - else() - set(LOCALEDIR ${CMAKE_INSTALL_PREFIX}/share/locale) - endif() - endif() - # gettext files - set(PO_FILE ${LCPATH}/messages.po) - set(MO_FILE ${LCPATH}/LC_MESSAGES/${PROJ}.mo) - set(RU_FILE ${LCPATH}/ru.po) -else() - add_definitions(-DNOGETTEXT) - set(PO_FILE) - set(MO_FILE) -endif() - -# pkgconfig find_package(PkgConfig REQUIRED) find_package(OpenGL REQUIRED) find_package(GLUT REQUIRED) -find_package(JPEG REQUIRED) -if(MODULES) - pkg_check_modules(${PROJ} REQUIRED ${MODULES}) -endif() - -#OpenMP -#include(FindOpenMP) -#if(OPENMP_FOUND) -# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") -# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") -# set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") -#endif() +if(NOT GLUT_FOUND OR NOT OPENGL_FOUND) + message("GLUT library not found, image view won't be available") +else() # exe file -add_executable(${PROJ} ${SOURCES} ${PO_FILE} ${MO_FILE}) -target_link_libraries(${PROJ} ${${PROJ}_LIBRARIES} ${OPENGL_LIBRARIES} ${JPEG_LIBRARIES} - ${GLUT_LIBRARIES} -lm -lpthread) -include_directories(${${PROJ}_INCLUDE_DIRS} ${OPENGL_INCLUDE_DIR} ${JPEG_INCLUDE_DIR} ${GLUT_INCLUDE_DIR}) -link_directories(${${PROJ}_LIBRARY_DIRS}) -add_definitions(${CFLAGS} -DLOCALEDIR=\"${LOCALEDIR}\" + +if(NOT DEFINED STANDALONE) + list(REMOVE_ITEM IMSOURCES main.c) + add_library(image_view_module ${IMSOURCES}) + + set(IMAGEVIEW_FOUND TRUE PARENT_SCOPE) + set(IMLIB ${IMLIB} PARENT_SCOPE) + if(DEFINED DEBUG) + set(LCPATH ${CMAKE_CURRENT_SOURCE_DIR}/locale/ru) + set(PO_FILE ${LCPATH}/messages.po) + set(RU_FILE ${LCPATH}/ru.po) + set(IMPO_FILE ${RU_FILE} PARENT_SCOPE) + add_custom_command( + OUTPUT ${PO_FILE} + COMMAND ${GETTEXT_XGETTEXT_EXECUTABLE} -D ${CMAKE_CURRENT_SOURCE_DIR} --from-code=koi8-r ${IMSOURCES} -c -k_ -kN_ -o ${PO_FILE} + COMMAND sed 's/charset=UTF-8/charset=koi8-r/' ${PO_FILE} | enconv > tmp && mv -f tmp ${PO_FILE} + COMMAND ${GETTEXT_MSGMERGE_EXECUTABLE} -Uis ${RU_FILE} ${PO_FILE} + DEPENDS ${IMSOURCES} + ) + endif() +else() + # cmake -DEBUG=1 -> debugging + if(DEFINED EBUG) + add_definitions(-DEBUG) + #set(CMAKE_VERBOSE_MAKEFILE ON) + endif() + + set(MINOR_VERSION "1") + set(MID_VERSION "0") + set(MAJOR_VERSION "0") + set(VERSION "${MAJOR_VERSION}.${MID_VERSION}.${MINOR_VERSION}") + + message("VER: ${VERSION}") + # change wrong behaviour with install prefix + if(CMAKE_INSTALL_PREFIX MATCHES "/usr/local") + message("Change default install path to /usr") + set(CMAKE_INSTALL_PREFIX "/usr") + endif() + message("Install dir prefix: ${CMAKE_INSTALL_PREFIX}") + add_definitions(${CFLAGS} -DLOCALEDIR=\"${LOCALEDIR}\" -DPACKAGE_VERSION=\"${VERSION}\" -DGETTEXT_PACKAGE=\"${PROJ}\" -DMINOR_VERSION=\"${MINOR_VERSION}\" -DMID_VERSION=\"${MID_VERSION}\" -DMAJOR_VERSION=\"${MAJOR_VESION}\" -DPROJNAME=\"${PROJ}\") -# Installation of the program -if(NOT DEFINED DEBUG) - INSTALL(FILES ${MO_FILE} DESTINATION "share/locale/ru/LC_MESSAGES") - #PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) - INSTALL(TARGETS ${PROJ} DESTINATION "bin") - #PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) - # Script to be executed at installation time (kind of post-intallation script) to - # change the right accesses on the installed files - #INSTALL(SCRIPT inst.cmake) -else() - install(CODE "MESSAGE(\"Don't install in DEBUG mode! First run cmake without -DEBUG defined.\")") -endif(NOT DEFINED DEBUG) + if(NOT DEFINED NOGETTEXT) + # directory should contain dir locale/ru for gettext translations + set(LCPATH ${CMAKE_SOURCE_DIR}/locale/ru) + if(NOT DEFINED LOCALEDIR) + if(DEFINED DEBUG) + set(LOCALEDIR ${CMAKE_CURRENT_SOURCE_DIR}/locale) + else() + set(LOCALEDIR ${CMAKE_INSTALL_PREFIX}/share/locale) + endif() + endif() + # gettext files + set(PO_FILE ${LCPATH}/messages.po) + set(MO_FILE ${LCPATH}/LC_MESSAGES/${PROJ}.mo) + set(RU_FILE ${LCPATH}/ru.po) + else() + add_definitions(-DNOGETTEXT) + set(PO_FILE) + set(MO_FILE) + endif() + + add_executable(${PROJ} ${IMSOURCES} ${PO_FILE} ${MO_FILE}) + + # Installation of the program + if(NOT DEFINED DEBUG) + INSTALL(FILES ${MO_FILE} DESTINATION "share/locale/ru/LC_MESSAGES") + #PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) + INSTALL(TARGETS ${PROJ} DESTINATION "bin") + #PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + # Script to be executed at installation time (kind of post-intallation script) to + # change the right accesses on the installed files + #INSTALL(SCRIPT inst.cmake) + else() + install(CODE "MESSAGE(\"Don't install in DEBUG mode! First run cmake without -DEBUG defined.\")") + endif(NOT DEFINED DEBUG) + + if(NOT DEFINED NOGETTEXT) + find_package(Gettext REQUIRED) + find_program(GETTEXT_XGETTEXT_EXECUTABLE xgettext) + if(NOT GETTEXT_XGETTEXT_EXECUTABLE OR NOT GETTEXT_MSGFMT_EXECUTABLE) + message(FATAL_ERROR "xgettext not found") + endif() + file(MAKE_DIRECTORY ${LCPATH}) + file(MAKE_DIRECTORY ${LCPATH}/LC_MESSAGES) + + add_custom_command( + OUTPUT ${PO_FILE} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMAND ${GETTEXT_XGETTEXT_EXECUTABLE} --from-code=utf-8 ${IMSOURCES} -c -k_ -kN_ -o ${PO_FILE} + COMMAND sed -i 's/charset=.*\\\\n/charset=koi8-r\\\\n/' ${PO_FILE} + COMMAND enconv ${PO_FILE} + DEPENDS ${IMSOURCES} + ) + # we need this to prewent ru.po from deleting by make clean + add_custom_target( + RU_FILE + COMMAND [ -f ${RU_FILE} ] && ${GETTEXT_MSGMERGE_EXECUTABLE} -Uis ${RU_FILE} ${PO_FILE} || cp ${PO_FILE} ${RU_FILE} + DEPENDS ${PO_FILE} + ) + add_custom_command( + OUTPUT ${MO_FILE} + COMMAND make RU_FILE && ${GETTEXT_MSGFMT_EXECUTABLE} ${RU_FILE} -o ${MO_FILE} + DEPENDS ${PO_FILE} + ) + endif(NOT DEFINED NOGETTEXT) +endif(NOT DEFINED STANDALONE) +target_link_libraries(${IMLIB} ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} -lm -lpthread) +include_directories(${${IMLIB}_INCLUDE_DIRS} ${OPENGL_INCLUDE_DIR} ${GLUT_INCLUDE_DIR}) +link_directories(${${IMLIB}_LIBRARY_DIRS}) +endif(NOT GLUT_FOUND OR NOT OPENGL_FOUND) -if(NOT DEFINED NOGETTEXT) -find_package(Gettext REQUIRED) -find_program(GETTEXT_XGETTEXT_EXECUTABLE xgettext) -if(NOT GETTEXT_XGETTEXT_EXECUTABLE OR NOT GETTEXT_MSGFMT_EXECUTABLE) - message(FATAL_ERROR "xgettext not found") -endif() -file(MAKE_DIRECTORY ${LCPATH}) -file(MAKE_DIRECTORY ${LCPATH}/LC_MESSAGES) -add_custom_command( - OUTPUT ${PO_FILE} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - COMMAND ${GETTEXT_XGETTEXT_EXECUTABLE} --from-code=utf-8 ${SOURCES} -c -k_ -kN_ -o ${PO_FILE} - COMMAND sed -i 's/charset=.*\\\\n/charset=koi8-r\\\\n/' ${PO_FILE} - COMMAND enconv ${PO_FILE} - DEPENDS ${SOURCES} -) -# we need this to prewent ru.po from deleting by make clean -add_custom_target( - RU_FILE - COMMAND [ -f ${RU_FILE} ] && ${GETTEXT_MSGMERGE_EXECUTABLE} -Uis ${RU_FILE} ${PO_FILE} || cp ${PO_FILE} ${RU_FILE} - DEPENDS ${PO_FILE} -) -add_custom_command( - OUTPUT ${MO_FILE} - COMMAND make RU_FILE && ${GETTEXT_MSGFMT_EXECUTABLE} ${RU_FILE} -o ${MO_FILE} - DEPENDS ${PO_FILE} -) -endif(NOT DEFINED NOGETTEXT) diff --git a/image_view_module/events.c b/image_view_module/events.c index 584a118..fedf85e 100644 --- a/image_view_module/events.c +++ b/image_view_module/events.c @@ -21,35 +21,22 @@ #include "events.h" #include "imageview.h" #include "macros.h" -/* - * Функции для работы с OpenGL'ными событиями + +/** + * manage pressed keys & menu items */ - -int ShowWavelet = 0; - -void keyPressed(unsigned char key, // код введенного символа - _U_ int x, _U_ int y){ // координаты мыши при нажатии клавиши - int _U_ mod = glutGetModifiers(), window = glutGetWindow(); - windowData *win = searchWindow_byGLID(window); +void processKeybrd(unsigned char key, int mod, int win_GL_ID, _U_ int x, _U_ int y){ + windowData *win = searchWindow_byGLID(win_GL_ID); if(!win) return; - //DBG("Key pressed. mod=%d, keycode=%d, point=(%d,%d)\n", mod, key, x,y); if((mod == GLUT_ACTIVE_CTRL) && (key == 'q' || key == 17)) exit(0); // ctrl + q switch(key){ case '1': // return zoom to 1 & image to 0 win->zoom = 1; win->x = 0; win->y = 0; break; -// case 'i': more_info = !more_info; -// break; - case 27: destroyWindow(window, OPENGL); - break; - case 'p': - printf("zoom = %f\n", win->zoom); + case 27: + destroyWindow_async(win_GL_ID); break; -// case 'm': createWindow(&mainWindow); -// break; -// case 'w': createWindow(&WaveWindow); -// break; case 'Z': win->zoom *= 1.1; calc_win_props(win, NULL, NULL); @@ -58,11 +45,22 @@ void keyPressed(unsigned char key, // win->zoom /= 1.1; calc_win_props(win, NULL, NULL); break; -// case 'h': createWindow(&SubWindow); -// break; } } +/* + * Process keyboard + */ +void keyPressed(unsigned char key, + _U_ int x, _U_ int y){ + int mod = glutGetModifiers(); + int window = glutGetWindow(); + //mod: GLUT_ACTIVE_SHIFT, GLUT_ACTIVE_CTRL, GLUT_ACTIVE_ALT; result is their sum + //DBG("Key pressed. mod=%d, keycode=%d, point=(%d,%d)\n", mod, key, x,y); + if((mod == GLUT_ACTIVE_CTRL) && (key == 'q' || key == 17)) exit(0); // ctrl + q + processKeybrd(key, mod, window, x, y); +} + void keySpPressed(_U_ int key, _U_ int x, _U_ int y){ // int mod = glutGetModifiers(); DBG("Sp. key pressed. mod=%d, keycode=%d, point=(%d,%d)\n", glutGetModifiers(), key, x,y); @@ -73,18 +71,25 @@ int movingwin = 0; // ==1 when user moves image by middle button void mousePressed(_U_ int key, _U_ int state, _U_ int x, _U_ int y){ // key: GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON, GLUT_RIGHT_BUTTON // state: GLUT_UP, GLUT_DOWN - int window = glutGetWindow(); + int window = glutGetWindow(), mod = glutGetModifiers(); windowData *win = searchWindow_byGLID(window); if(!win) return; if(state == GLUT_DOWN){ oldx = x; oldy = y; float X,Y; conv_mouse_to_image_coords(x,y,&X,&Y,win); - DBG("press in (%d, %d) == (%f, %f) on image", x,y,X,Y); + DBG("press in (%d, %d) == (%f, %f) on image; mod == %d", x,y,X,Y, mod); if(key == GLUT_MIDDLE_BUTTON) movingwin = 1; if(key == 3){ // wheel UP + if(mod == 0) win->y += 10.*win->zoom; // nothing pressed - scroll up + else if(mod == GLUT_ACTIVE_SHIFT) win->x -= 10.*win->zoom; // shift pressed - scroll left + else if(mod == GLUT_ACTIVE_CTRL) win->zoom *= 1.1; // ctrl+wheel up == zoom+ }else if(key == 4){ // wheel DOWN + if(mod == 0) win->y -= 10.*win->zoom; // nothing pressed - scroll down + else if(mod == GLUT_ACTIVE_SHIFT) win->x += 10.*win->zoom; // shift pressed - scroll right + else if(mod == GLUT_ACTIVE_CTRL) win->zoom /= 1.1; // ctrl+wheel down == zoom- } + calc_win_props(win, NULL, NULL); }else{ movingwin = 0; } @@ -134,21 +139,27 @@ void mouseMove(_U_ int x, _U_ int y){ } } +void menuEvents(int opt){ + FNAME(); + int window = glutGetWindow(); + if(opt == 'q') exit(0); + processKeybrd((unsigned char)opt, 0, window, 0, 0); +} + /** * winID - inner !!! */ -void createMenu(_U_ int winID){ - glutCreateMenu(menuEvents); +void createMenu(int GL_ID){ + FNAME(); + windowData *win; + win = searchWindow_byGLID(GL_ID); + glutSetWindow(GL_ID); + if(win->menu) glutDestroyMenu(win->menu); + win->menu = glutCreateMenu(menuEvents); + DBG("created menu %d\n", win->menu); glutAddMenuEntry("Quit (ctrl+q)", 'q'); glutAddMenuEntry("Close this window (ESC)", 27); -// if(window == &mainWindow){ // пункты меню главного окна - glutAddMenuEntry("Info in stderr (i)", 'i'); -// } - ; + glutAddMenuEntry("Restore zoom (1)", '1'); glutAttachMenu(GLUT_RIGHT_BUTTON); } -void menuEvents(int opt){ - if(opt == 'q') exit(0); - keyPressed((unsigned char)opt, 0, 0); -} diff --git a/image_view_module/imageview.c b/image_view_module/imageview.c index c6d9266..529cd19 100644 --- a/image_view_module/imageview.c +++ b/image_view_module/imageview.c @@ -30,6 +30,7 @@ volatile int wannacreate = 0; // flag: ==1 if someone wants to create window windowData *wininiptr = NULL; int initialized = 0; // ==1 if GLUT is initialized; ==0 after clear_GL_context +int wannakill_GL_ID = 0; // GL_ID of window for asynchroneous killing void createWindow(windowData *win); void RedrawWindow(); @@ -88,19 +89,22 @@ void createWindow(windowData *win){ glGenTextures(1, &(win->Tex)); calc_win_props(win, NULL, NULL); win->zoom = 1. / win->Daspect; -// createMenu(win->ID); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, win->Tex); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +// glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, win->image->w, win->image->h, 0, GL_RGB, GL_UNSIGNED_BYTE, win->image->rawdata); glDisable(GL_TEXTURE_2D); totWindows++; + createMenu(win->GL_ID); DBG("OK, total opened windows: %d", totWindows); } @@ -108,22 +112,23 @@ void createWindow(windowData *win){ int killwindow(int GL_ID){ DBG("try to kill win GL_ID=%d", GL_ID); windowData *win; - int canceled = 1; win = searchWindow_byGLID(GL_ID); if(!win) return 0; - if(!pthread_cancel(win->thread)){ // cancel thread changing data - canceled = 0; + glutSetWindow(GL_ID); // obviously set window (for closing from menu) + if(!win->killthread){ + pthread_mutex_lock(&win->mutex); + // say changed thread to die + win->killthread = 1; + pthread_mutex_unlock(&win->mutex); + DBG("wait for changed thread"); + pthread_join(win->thread, NULL); // wait while thread dies } -// pthread_join(win->thread, NULL); - glDeleteTextures(1, &win->Tex); - glFinish(); + if(win->menu) glutDestroyMenu(win->menu); glutDestroyWindow(win->GL_ID); win->GL_ID = 0; // reset for forEachWindow() - pthread_mutex_unlock(&win->mutex); - if(!canceled && !pthread_cancel(win->thread)){ // cancel thread changing data - WARN(_("can't cancel a thread!")); - } - pthread_join(win->thread, NULL); + DBG("destroy texture %d", win->Tex); + glDeleteTextures(1, &(win->Tex)); + glFinish(); if(!removeWindow(win->ID)) WARNX(_("Error removing from list")); totWindows--; return 1; @@ -138,16 +143,28 @@ int killwindow(int GL_ID){ int destroyWindow(int window, winIdType type){ if(!initialized) return 0; int r = 0; + DBG("lock"); pthread_mutex_lock(&winini_mutex); + DBG("locked"); if(type == INNER){ windowData *win = searchWindow(window); if(win) r = killwindow(win->GL_ID); }else r = killwindow(window); pthread_mutex_unlock(&winini_mutex); + DBG("window killed"); return r; } +/** + * asynchroneous destroying - for using from menu + */ +void destroyWindow_async(int window_GL_ID){ + pthread_mutex_lock(&winini_mutex); + wannakill_GL_ID = window_GL_ID; + pthread_mutex_unlock(&winini_mutex); +} + void renderBitmapString(float x, float y, void *font, char *string, GLubyte *color){ if(!initialized) return; char *c; @@ -235,9 +252,17 @@ void RedrawWindow(){ * waits for global signals to create windows & make other actions */ void *Redraw(_U_ void *arg){ +// pthread_cond_t fakeCond = PTHREAD_COND_INITIALIZER; +// struct timeval tv; +// struct timespec timeToWait; +// struct timeval now; while(1){ pthread_mutex_lock(&winini_mutex); - if(!initialized) return NULL; + if(!initialized){ + DBG("!initialized"); + pthread_mutex_unlock(&winini_mutex); + pthread_exit(NULL); + } if(wannacreate){ // someone asks to create window DBG("call for window creating, id: %d", wininiptr->ID); createWindow(wininiptr); @@ -245,9 +270,28 @@ void *Redraw(_U_ void *arg){ wininiptr = NULL; wannacreate = 0; } + if(wannakill_GL_ID){ + usleep(10000); // wait a little to be sure that caller is closed + killwindow(wannakill_GL_ID); + wannakill_GL_ID = 0; + } forEachWindow(redisplay); +/* gettimeofday(&now,NULL); + timeToWait.tv_sec = now.tv_sec; + timeToWait.tv_nsec = now.tv_usec * 1000UL + 10000000UL; + pthread_cond_timedwait(&fakeCond, &winini_mutex, &timeToWait);*/ pthread_mutex_unlock(&winini_mutex); + //pthread_testcancel(); if(totWindows) glutMainLoopEvent(); // process actions if there are windows +/* gettimeofday(&now,NULL); + timeToWait.tv_sec = now.tv_sec; + timeToWait.tv_nsec = now.tv_usec * 1000UL + 10000000UL; + pthread_mutex_lock(&fakeMutex); + pthread_cond_timedwait(&fakeCond, &fakeMutex, &timeToWait); + pthread_mutex_unlock(&fakeMutex);*/ +/* tv.tv_sec = 0; + tv.tv_usec = 10000; + select(0, NULL, NULL, NULL, &tv);*/ usleep(10000); } return NULL; @@ -366,12 +410,18 @@ void killwindow_v(int GL_ID){ void clear_GL_context(){ FNAME(); if(!initialized) return; + DBG("lock"); pthread_mutex_lock(&winini_mutex); - forEachWindow(killwindow_v); - pthread_cancel(GLUTthread); // kill main GLUT thread - pthread_join(GLUTthread, NULL); initialized = 0; + DBG("locked"); + // kill main GLUT thread +// pthread_cancel(GLUTthread); pthread_mutex_unlock(&winini_mutex); + forEachWindow(killwindow_v); + DBG("join"); + pthread_join(GLUTthread, NULL); // wait while main thread exits +// pthread_mutex_unlock(&winini_mutex); + DBG("main GL thread cancelled"); } diff --git a/image_view_module/imageview.h b/image_view_module/imageview.h index 2c197dd..87ca486 100644 --- a/image_view_module/imageview.h +++ b/image_view_module/imageview.h @@ -45,4 +45,6 @@ void calc_win_props(windowData *win, GLfloat *Wortho, GLfloat *Hortho); void conv_mouse_to_image_coords(int x, int y, float *X, float *Y, windowData *window); void conv_image_to_mouse_coords(float X, float Y, int *x, int *y, windowData *window); +void destroyWindow_async(int window_GL_ID); + #endif // __BMPVIEW_H__ diff --git a/image_view_module/list.h b/image_view_module/list.h index cd6ef56..e0fedcf 100644 --- a/image_view_module/list.h +++ b/image_view_module/list.h @@ -48,8 +48,10 @@ typedef struct{ float x0; float y0;// center of window for coords conversion float zoom; // zoom aspect float Daspect; // aspect ratio between image & window sizes + int menu; // window menu identifier pthread_t thread; // identificator of thread that changes window data pthread_mutex_t mutex;// mutex for operations with image + int killthread; // flag for killing data changing thread & also signal that there's no threads } windowData; diff --git a/image_view_module/locale/ru/LC_MESSAGES/image_view_module.mo b/image_view_module/locale/ru/LC_MESSAGES/image_view_module.mo new file mode 100644 index 0000000..8431b67 Binary files /dev/null and b/image_view_module/locale/ru/LC_MESSAGES/image_view_module.mo differ diff --git a/image_view_module/locale/ru/LC_MESSAGES/openglview.mo b/image_view_module/locale/ru/LC_MESSAGES/openglview.mo deleted file mode 100644 index 88e0b13..0000000 Binary files a/image_view_module/locale/ru/LC_MESSAGES/openglview.mo and /dev/null differ diff --git a/image_view_module/locale/ru/messages.po b/image_view_module/locale/ru/messages.po index 21fb0ab..6caa9a1 100644 --- a/image_view_module/locale/ru/messages.po +++ b/image_view_module/locale/ru/messages.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-02-28 19:36+0300\n" +"POT-Creation-Date: 2015-03-02 13:58+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -43,20 +43,15 @@ msgstr "" msgid "Can't munmap" msgstr "" -#. cancel thread changing data -#: /home/eddy/tmp/image_view_module/imageview.c:124 -msgid "can't cancel a thread!" -msgstr "" - -#: /home/eddy/tmp/image_view_module/imageview.c:127 +#: /home/eddy/tmp/image_view_module/imageview.c:132 msgid "Error removing from list" msgstr "" -#: /home/eddy/tmp/image_view_module/imageview.c:318 +#: /home/eddy/tmp/image_view_module/imageview.c:362 msgid "Can't init mutex!" msgstr "" #. "Уже инициализировано!" -#: /home/eddy/tmp/image_view_module/imageview.c:345 +#: /home/eddy/tmp/image_view_module/imageview.c:389 msgid "Already initialized!" msgstr "" diff --git a/image_view_module/locale/ru/ru.po b/image_view_module/locale/ru/ru.po index 00c5d6e..43e1df6 100644 --- a/image_view_module/locale/ru/ru.po +++ b/image_view_module/locale/ru/ru.po @@ -7,7 +7,7 @@ msgid "" msgstr "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" - "POT-Creation-Date: 2015-02-28 19:32+0300\n" + "POT-Creation-Date: 2015-03-02 12:05+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,15 +17,15 @@ msgstr "Project-Id-Version: PACKAGE VERSION\n" "Content-Transfer-Encoding: 8bit\n" #. "Уже инициализировано!" -#: /home/eddy/tmp/image_view_module/imageview.c:345 +#: /home/eddy/tmp/image_view_module/imageview.c:389 msgid "Already initialized!" -msgstr "" +msgstr "Уже инициализировано!" #: /home/eddy/tmp/image_view_module/macros.c:183 msgid "Can't close mmap'ed file" msgstr "Не могу закрыть mmap'нутый файл" -#: /home/eddy/tmp/image_view_module/imageview.c:318 +#: /home/eddy/tmp/image_view_module/imageview.c:362 msgid "Can't init mutex!" msgstr "Не могу инициировать взаимное исключение!" @@ -43,7 +43,7 @@ msgstr " msgid "Can't stat %s" msgstr "Не могу выполнить stat для %s" -#: /home/eddy/tmp/image_view_module/imageview.c:127 +#: /home/eddy/tmp/image_view_module/imageview.c:132 msgid "Error removing from list" msgstr "Ошибка удаления из списка" @@ -55,11 +55,9 @@ msgstr " msgid "No filename given!" msgstr "Не указано имя файла!" -#. cancel thread changing data -#: /home/eddy/tmp/image_view_module/imageview.c:124 -msgid "can't cancel a thread!" -msgstr "Не могу отменить выполнение потока!" - #, fuzzy #~ msgid "Can't init main GLUT mutex!" #~ msgstr "Не могу инициировать взаимное исключение!" + +#~ msgid "can't cancel a thread!" +#~ msgstr "Не могу отменить выполнение потока!" diff --git a/image_view_module/main.c b/image_view_module/main.c index 5a8160b..6a39fb4 100644 --- a/image_view_module/main.c +++ b/image_view_module/main.c @@ -29,15 +29,24 @@ void* change_image(void *data){ FNAME(); + //struct timeval tv; windowData *win = (windowData*) data; int w = win->image->w, h = win->image->h, x,y, id = win->ID; GLubyte i; DBG("w=%d, h=%d",w,h); for(i = 1; ;i++){ // DBG("search to refresh %d", id); - if(!searchWindow(id)) pthread_exit(NULL); + if(!searchWindow(id)){ + DBG("Window deleted"); + pthread_exit(NULL); + } // DBG("found, lock mutex"); pthread_mutex_lock(&win->mutex); + if(win->killthread){ + pthread_mutex_unlock(&win->mutex); + DBG("got killthread"); + pthread_exit(NULL); + } // DBG("refresh"); GLubyte *raw = win->image->rawdata; for(y = 0; y < h; y++){ @@ -57,7 +66,41 @@ void* change_image(void *data){ win->image->changed = 1; pthread_mutex_unlock(&win->mutex); usleep(10000); - //sleep(1); + /*tv.tv_sec = 0; + tv.tv_usec = 10000; + select(0, NULL, NULL, NULL, &tv);*/ + } +} + +void* another_change(void *data){ + FNAME(); + windowData *win = (windowData*) data; + int w = win->image->w, h = win->image->h, x,y, id = win->ID; + GLubyte i; + for(i = 1; ;i++){ + if(!searchWindow(id)){ + DBG("Window deleted"); + pthread_exit(NULL); + } + pthread_mutex_lock(&win->mutex); + GLubyte *raw = win->image->rawdata; + for(y = 0; y < h; y++){ + if(y%20 == 19){ + raw += w*3; + continue; + } + for(x = 0; x < w; x++){ + if(x%20 != 19){ + if(i < 80) raw[0]--; + else if(i < 170) raw[1]--; + else raw[2]--; + } + raw += 3; + } + } + win->image->changed = 1; + pthread_mutex_unlock(&win->mutex); + usleep(10000); } } @@ -65,6 +108,7 @@ void *main_thread(_U_ void *none){ // while(1){}; rawimage im; windowData *mainwin, *win, *third; + pthread_t mainthread; int w = 640, h = 480; im.protected = 1; im.rawdata = MALLOC(GLubyte, w*h*3); @@ -72,11 +116,14 @@ void *main_thread(_U_ void *none){ mainwin = createGLwin("Sample window", w, h, &im); DBG("ok"); if(!mainwin) ERRX("can't create main"); - pthread_create(&mainwin->thread, NULL, &change_image, (void*)mainwin); +// pthread_create(&mainwin->thread, NULL, &change_image, (void*)mainwin); + pthread_create(&mainthread, NULL, &another_change, (void*)mainwin); + mainwin->killthread = 1; // say that there's no thread for manipulating win = createGLwin("Second window", w/2, h/2, NULL); if(!win) ERRX("can't create second"); pthread_create(&win->thread, NULL, &change_image, (void*)win); - pthread_join(mainwin->thread, NULL); + //pthread_join(mainwin->thread, NULL); + pthread_join(mainthread, NULL); pthread_join(win->thread, NULL); clear_GL_context(); WARNX("Two windows closed, create another one");