📄 sdlevent.c
字号:
/* * Copyright (C) 2000-2004 Damien Douxchamps <ddouxchamps@users.sf.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "coriander.h"#ifdef HAVE_SDLLIB//extern GtkWidget *main_window;//extern watchthread_info_t watchthread_info;//extern camera_t* camera;//extern int WM_cancel_display;//extern cursor_info_t cursor_info;//extern xvinfo_t xvinfo;//extern whitebal_data_t* whitebal_data;// This should be probed automatically.// This limitation might come from the video RAM.#define MAX_DISPLAY_WIDTH 8192#define MAX_DISPLAY_HEIGHT 8192intSDLEventStartThread(chain_t *display_service){ displaythread_info_t *info; info=(displaythread_info_t*)display_service->data; pthread_mutex_init(&info->mutex_cancel_event, NULL); pthread_mutex_init(&info->mutex_event, NULL); pthread_mutex_lock(&info->mutex_cancel_event); info->cancel_event_req=0; pthread_mutex_unlock(&info->mutex_cancel_event); if (pthread_create(&info->event_thread, NULL, SDLEventThread, (void*)display_service)) return(1); else return(0);}void*SDLEventThread(void *arg){ chain_t* display_service; displaythread_info_t *info; display_service=(chain_t*)arg; pthread_mutex_lock(&display_service->mutex_data); info=(displaythread_info_t*)display_service->data; pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL); pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL); pthread_mutex_unlock(&display_service->mutex_data); while (1) { pthread_mutex_lock(&info->mutex_cancel_event); if (info->cancel_event_req>0) { pthread_mutex_unlock(&info->mutex_cancel_event); return ((void*)1); } else { pthread_mutex_unlock(&info->mutex_cancel_event); pthread_mutex_lock(&info->mutex_event); if (!SDLHandleEvent(display_service)) { pthread_mutex_unlock(&info->mutex_event); // SDL_QUIT called, close display thread DisplayStopThread(camera); // the following is only for the display_service button to be updated. WM_cancel_display=1; break; } else { pthread_mutex_unlock(&info->mutex_event); usleep(DELAY); } } } return ((void*)0);}voidSDLEventStopThread(chain_t *display_service){ displaythread_info_t *info; info=(displaythread_info_t*)display_service->data; // send request for cancellation: pthread_mutex_lock(&info->mutex_cancel_event); info->cancel_event_req=1; pthread_mutex_unlock(&info->mutex_cancel_event); // when cancellation occured, join: pthread_join(info->event_thread, NULL);}intSDLHandleEvent(chain_t *display_service){ displaythread_info_t *info; SDL_Event event; info=(displaythread_info_t*)display_service->data; while ( SDL_PollEvent(&event) ) { pthread_mutex_lock(&display_service->mutex_data); switch(event.type) { case SDL_VIDEORESIZE: SDLResizeDisplay(display_service, event.resize.w, event.resize.h); break; case SDL_KEYDOWN: OnKeyPressed(display_service,event.key.keysym.sym, event.key.keysym.mod); break; case SDL_KEYUP: OnKeyReleased(display_service,event.key.keysym.sym, event.key.keysym.mod); break; case SDL_MOUSEBUTTONDOWN: OnMouseDown(display_service,event.button.button, event.button.x, event.button.y); break; case SDL_MOUSEBUTTONUP: OnMouseUp(display_service,event.button.button, event.button.x, event.button.y); break; case SDL_MOUSEMOTION: OnMouseMotion(display_service, event.motion.x, event.motion.y); break; case SDL_QUIT: pthread_mutex_unlock(&display_service->mutex_data); return(0); break; } pthread_mutex_unlock(&display_service->mutex_data); } return(1);}voidOnKeyPressed(chain_t *display_service, int key, int mod){ displaythread_info_t *info; info=(displaythread_info_t*)display_service->data; //printf ("%s: 0x%02x\n", __FUNCTION__, key); switch (key) { case SDLK_n: // set display to normal size SDLResizeDisplay(display_service, display_service->current_buffer->width, display_service->current_buffer->height); break; case SDLK_f: // toggle fullscreen mode SDL_WM_ToggleFullScreen(info->sdlvideo); break; case SDLK_c: // crop image SDLCropImage(display_service); break; case SDLK_m: // set F7 image to max size SDLSetMaxSize(display_service); break; case SDLK_PAGEUP: // image size +10% SDLResizeDisplay(display_service, info->sdlvideorect.w*10/9, info->sdlvideorect.h*10/9); break; case SDLK_PAGEDOWN: // image size -10% SDLResizeDisplay(display_service, info->sdlvideorect.w*9/10, info->sdlvideorect.h*9/10); break;#if 1 /* This should leave. SDL supplies the raw key with modifiers, so e.g. 'a' = SDLK_a,0 'A' = SDLK_a,KMOD_SHIFT, etc. On my keyboard, '<' is SDLK_COMMA,KMOD_SHIFT and SDLK_GREATER will never arrive here. */ case SDLK_GREATER: // image size *2 if (mod&(KMOD_SHIFT)) { SDLResizeDisplay(display_service, info->sdlvideorect.w/2, info->sdlvideorect.h/2); } else { SDLResizeDisplay(display_service, info->sdlvideorect.w*2, info->sdlvideorect.h*2); } break; case SDLK_LESS: // image size /2 if (mod&(KMOD_SHIFT)) { SDLResizeDisplay(display_service, info->sdlvideorect.w*2, info->sdlvideorect.h*2); } else { SDLResizeDisplay(display_service, info->sdlvideorect.w/2, info->sdlvideorect.h/2); } break;#endif } }voidOnKeyReleased(chain_t *display_service, int key, int mod){}voidOnMouseDown(chain_t *display_service, int button, int x, int y){ displaythread_info_t *info; Format7ModeInfo_t* f7info; info=(displaythread_info_t*)display_service->data; if (camera->misc_info.format==FORMAT_SCALABLE_IMAGE_SIZE) { f7info=&camera->format7_info.mode[camera->misc_info.mode-MODE_FORMAT7_MIN]; } switch (button) { case SDL_BUTTON_LEFT: pthread_mutex_lock(&watchthread_info.mutex_area); watchthread_info.draw=1; watchthread_info.mouse_down=1; // there is some adaptation because the display size can be different // from the real image size. (i.e. the image can be resized) watchthread_info.first[0]= ((x*display_service->current_buffer->width /info->sdlvideorect.w)); watchthread_info.first[1]= ((y*display_service->current_buffer->height/info->sdlvideorect.h)); // zero size at first click, -> copy click coordinate to second corner watchthread_info.second[0]=watchthread_info.first[0]; watchthread_info.second[1]=watchthread_info.first[1]; watchthread_info.upper_left[0]=watchthread_info.first[0]; watchthread_info.upper_left[1]=watchthread_info.first[1]; watchthread_info.lower_right[0]=watchthread_info.first[0]; watchthread_info.lower_right[1]=watchthread_info.first[1]; GetValidF7Crop(&watchthread_info, display_service); pthread_mutex_unlock(&watchthread_info.mutex_area); break; case SDL_BUTTON_MIDDLE: x=x*display_service->current_buffer->width/info->sdlvideorect.w; //rescaling y=y*display_service->current_buffer->height/info->sdlvideorect.h; // THIS IS ONLY VALID FOR YUYV!! cursor_info.col_y=info->sdloverlay->pixels[0][(y*display_service->current_buffer->width+x)*2]; cursor_info.col_u=info->sdloverlay->pixels[0][(((y*display_service->current_buffer->width+x)>>1)<<2)+1]-127; cursor_info.col_v=info->sdloverlay->pixels[0][(((y*display_service->current_buffer->width+x)>>1)<<2)+3]-127; YUV2RGB(cursor_info.col_y, cursor_info.col_u, cursor_info.col_v, cursor_info.col_r, cursor_info.col_g, cursor_info.col_b); cursor_info.x=x; cursor_info.y=y; cursor_info.update_req=1; break; case SDL_BUTTON_RIGHT: //whitebal_data->x=x*display_service->current_buffer->width/info->sdlvideorect.w; //rescaling //whitebal_data->y=y*display_service->current_buffer->height/info->sdlvideorect.h; //whitebal_data->service=display_service; //pthread_create(&whitebal_data->thread, NULL, AutoWhiteBalance, (void*)&whitebal_data); break; default: //fprintf(stderr,"Bad button ID in SDL!\n"); break; }}voidOnMouseUp(chain_t *display_service, int button, int x, int y){ displaythread_info_t *info; info=(displaythread_info_t*)display_service->data; switch (button) { case SDL_BUTTON_LEFT: pthread_mutex_lock(&watchthread_info.mutex_area); watchthread_info.mouse_down=0; // there is some adaptation because the display size can be different // from the real image size. (i.e. the image can be resized) //info->lower_right[0]=x*display_service->current_buffer->width/info->sdlvideorect.w; //info->lower_right[1]=y*display_service->current_buffer->height/info->sdlvideorect.h; pthread_mutex_unlock(&watchthread_info.mutex_area); break; case SDL_BUTTON_MIDDLE: break; case SDL_BUTTON_RIGHT: break; default: //fprintf(stderr,"Bad button ID in SDL!\n"); break; }}voidOnMouseMotion(chain_t *display_service, int x, int y){ displaythread_info_t *info; info=(displaythread_info_t*)display_service->data; pthread_mutex_lock(&watchthread_info.mutex_area); if (watchthread_info.mouse_down==1) { watchthread_info.second[0]=x*display_service->current_buffer->width/info->sdlvideorect.w; watchthread_info.second[1]=y*display_service->current_buffer->height/info->sdlvideorect.h; // we need to flip the corners if the pointer moves backwards if (watchthread_info.second[0]<watchthread_info.first[0]) watchthread_info.upper_left[0]=watchthread_info.second[0]; else watchthread_info.upper_left[0]=watchthread_info.first[0]; if (watchthread_info.second[1]<watchthread_info.first[1]) watchthread_info.upper_left[1]=watchthread_info.second[1]; else watchthread_info.upper_left[1]=watchthread_info.first[1]; if (watchthread_info.second[0]>=watchthread_info.first[0]) watchthread_info.lower_right[0]=watchthread_info.second[0]; else watchthread_info.lower_right[0]=watchthread_info.first[0]; if (watchthread_info.second[1]>=watchthread_info.first[1]) watchthread_info.lower_right[1]=watchthread_info.second[1]; else watchthread_info.lower_right[1]=watchthread_info.first[1]; GetValidF7Crop(&watchthread_info,display_service); } pthread_mutex_unlock(&watchthread_info.mutex_area); }voidSDLResizeDisplay(chain_t *display_service, int width, int height){ displaythread_info_t *info; info=(displaythread_info_t*)display_service->data; int prev_height, prev_width; prev_width=info->sdlvideorect.w; prev_height=info->sdlvideorect.h; // check that the size is not too small or too large. if ((width<1)||(height<1)||(width>MAX_DISPLAY_WIDTH)||(height>MAX_DISPLAY_HEIGHT)) return; if (display_service->camera->prefs.display_keep_ratio>0) { // keep aspect ratio and resize following which dimension we change if (abs(width-info->sdlvideorect.w) >= (abs(height-info->sdlvideorect.h))) { // we changed the width, set height accordingly info->sdlvideorect.w = width; info->sdlvideorect.h = (width * display_service->current_buffer->height) / display_service->current_buffer->width; } else { // we changed the height, set width accordingly info->sdlvideorect.w = (height * display_service->current_buffer->width) / display_service->current_buffer->height; info->sdlvideorect.h = height; } } else { // bypass aspect keep: info->sdlvideorect.w = width; info->sdlvideorect.h = height; } // maximize display size to XV size if necessary if ((xvinfo.max_width!=-1)&&(xvinfo.max_height!=-1)) { if (info->sdlvideorect.w>xvinfo.max_width) { info->sdlvideorect.w=xvinfo.max_width; } if (info->sdlvideorect.h>xvinfo.max_height) { info->sdlvideorect.h=xvinfo.max_height; } } // if size change is effective, re-set SDL stuff if ((prev_width!=info->sdlvideorect.w)||(prev_height!=info->sdlvideorect.h)) { // Free overlay & video surface SDL_FreeYUVOverlay(info->sdloverlay); SDL_FreeSurface(info->sdlvideo); // new video mode info->sdlvideo = SDL_SetVideoMode(info->sdlvideorect.w, info->sdlvideorect.h, info->sdlbpp, info->sdlflags); if (info->sdlvideo == NULL) { MainError(SDL_GetError()); SDL_Quit(); return; } // Create YUV Overlay info->sdloverlay = SDL_CreateYUVOverlay(display_service->current_buffer->width, display_service->current_buffer->height, SDL_YUY2_OVERLAY, info->sdlvideo); if (info->sdloverlay==NULL) { MainError(SDL_GetError()); SDL_Quit(); return; } } }voidSDLCropImage(chain_t *display_service){ pthread_mutex_lock(&watchthread_info.mutex_area); watchthread_info.draw=0; if (display_service->current_buffer->format==FORMAT_SCALABLE_IMAGE_SIZE) watchthread_info.crop=1; pthread_mutex_unlock(&watchthread_info.mutex_area); }voidSDLSetMaxSize(chain_t *display_service){ pthread_mutex_lock(&watchthread_info.mutex_area); watchthread_info.draw=0; if (display_service->current_buffer->format==FORMAT_SCALABLE_IMAGE_SIZE) { watchthread_info.crop=1; watchthread_info.pos[0]=0; watchthread_info.pos[1]=0; watchthread_info.size[0]=camera->format7_info.mode[camera->misc_info.mode-MODE_FORMAT7_MIN].max_size_x; watchthread_info.size[1]=camera->format7_info.mode[camera->misc_info.mode-MODE_FORMAT7_MIN].max_size_y; } pthread_mutex_unlock(&watchthread_info.mutex_area);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -