diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/Makefile | 10 | ||||
-rw-r--r-- | modules/pdp_del.c | 56 | ||||
-rw-r--r-- | modules/pdp_gradient.c | 7 | ||||
-rw-r--r-- | modules/pdp_noise.c | 10 | ||||
-rw-r--r-- | modules/pdp_qt.c | 18 | ||||
-rw-r--r-- | modules/pdp_sdl.c | 245 | ||||
-rw-r--r-- | modules/pdp_v4l.c | 61 | ||||
-rw-r--r-- | modules/pdp_xv.c | 132 |
8 files changed, 369 insertions, 170 deletions
diff --git a/modules/Makefile b/modules/Makefile index 8f743aa..09a9ce3 100644 --- a/modules/Makefile +++ b/modules/Makefile @@ -2,13 +2,15 @@ current: all_modules include ../Makefile.config -OBJECTS = pdp_xv.o pdp_qt.o pdp_add.o pdp_reg.o pdp_conv.o \ - pdp_mix.o pdp_v4l.o pdp_affine.o pdp_del.o pdp_mul.o pdp_randmix.o \ +PDP_MOD = pdp_add.o pdp_reg.o pdp_conv.o \ + pdp_mix.o pdp_affine.o pdp_del.o pdp_mul.o pdp_randmix.o \ pdp_snap.o pdp_trigger.o pdp_bq.o pdp_noise.o pdp_gradient.o \ pdp_route.o pdp_gain.o pdp_grey.o pdp_chrot.o pdp_scope.o \ - pdp_scale.o pdp_zoom.o pdp_scan.o pdp_sdl.o pdp_cheby.o + pdp_scale.o pdp_zoom.o pdp_scan.o pdp_cheby.o pdp_scanxy.o \ + pdp_grey2mask.o pdp_constant.o pdp_slice_cut.o pdp_slice_glue.o -all_modules: $(OBJECTS) +# build portable and optional modules +all_modules: $(PDP_MOD) $(PDP_OPTMOD) clean: rm -f *~ diff --git a/modules/pdp_del.c b/modules/pdp_del.c index 97e47fd..50813e3 100644 --- a/modules/pdp_del.c +++ b/modules/pdp_del.c @@ -23,29 +23,19 @@ #include "pdp.h" - - - - - - - - - - - - typedef struct pdp_del_struct { - t_object x_obj; - t_float x_f; + t_object x_obj; + t_float x_f; - t_outlet *x_outlet0; + t_outlet *x_outlet0; + + t_outlet **x_outlet; - int *x_packet; - int x_order; - int x_head; - int x_delay; + int *x_packet; + int x_order; + int x_head; + int x_delay; } t_pdp_del; @@ -63,7 +53,7 @@ static void pdp_del_input_0(t_pdp_del *x, t_symbol *s, t_floatarg f) /* if this is a process message, start the processing + propagate stuff to outputs */ if (s == gensym("register_ro")){ - in = (x->x_head & (x->x_order-1)); + in = (x->x_head % x->x_order); //post("pdp_del: marking unused packed id=%d on loc %d", x->x_packet[0], in); pdp_packet_mark_unused(x->x_packet[in]); packet = pdp_packet_copy_ro((int)f); @@ -71,7 +61,7 @@ static void pdp_del_input_0(t_pdp_del *x, t_symbol *s, t_floatarg f) //post("pdp_del: writing packed id=%d on loc %d", packet, in); } else if (s == gensym("process")){ - out = ((x->x_head + x->x_delay) & (x->x_order-1)); + out = (((x->x_head + x->x_delay)) % x->x_order); packet = x->x_packet[out]; if (-1 != packet){ @@ -83,7 +73,7 @@ static void pdp_del_input_0(t_pdp_del *x, t_symbol *s, t_floatarg f) else { //post("pdp_del: packet %d is empty", out); } - x->x_head--; + x->x_head = (x->x_head + x->x_order - 1) % x->x_order; } @@ -132,39 +122,19 @@ void *pdp_del_new(t_floatarg forder, t_floatarg fdel) int i; t_pdp_del *x = (t_pdp_del *)pd_new(pdp_del_class); - del = order; order++; if (del < 0) del = 0; - - if (order <= 2) order = 2; - else { - - order--; - logorder = 1; - - while ((order | 1) != 1) { - order >>= 1; - logorder++; - } - - order = 1 << logorder; - } - - post("pdp_del: order = %d", order); + //post("pdp_del: order = %d", order); x->x_order = order; x->x_packet = (int *)malloc(sizeof(int)*order); for(i=0; i<order; i++) x->x_packet[i] = -1; - x->x_delay = del; - - inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("delay")); - x->x_outlet0 = outlet_new(&x->x_obj, &s_anything); diff --git a/modules/pdp_gradient.c b/modules/pdp_gradient.c index 5c92e12..3af2a84 100644 --- a/modules/pdp_gradient.c +++ b/modules/pdp_gradient.c @@ -265,8 +265,11 @@ static void pdp_gradient_input_0(t_pdp_gradient *x, t_symbol *s, t_floatarg f) /* add the process method and callback to the process queue */ - - pdp_queue_add(x, pdp_gradient_process, pdp_gradient_sendpacket, &x->x_queue_id); + // since the process method creates a packet, this is not processed in the thread + // $$$TODO: fix this + //pdp_queue_add(x, pdp_gradient_process, pdp_gradient_sendpacket, &x->x_queue_id); + pdp_gradient_process(x); + pdp_gradient_sendpacket(x); } } diff --git a/modules/pdp_noise.c b/modules/pdp_noise.c index f1a4661..84f4a72 100644 --- a/modules/pdp_noise.c +++ b/modules/pdp_noise.c @@ -149,16 +149,14 @@ static void pdp_noise_bang(t_pdp_noise *x) /* release the packet */ -} +} static void pdp_noise_dim(t_pdp_noise *x, t_floatarg w, t_floatarg h) { - if (w<32.0f) w = 32.0f; - if (h<32.0f) h = 32.0f; - - x->x_width = (unsigned int)w; - x->x_height = (unsigned int)h; + x->x_width = pdp_imageproc_legalwidth((int)w); + x->x_height = pdp_imageproc_legalheight((int)h); + //post("dims %d %d", x->x_width, x->x_height); } diff --git a/modules/pdp_qt.c b/modules/pdp_qt.c index 1c778d5..8ed633d 100644 --- a/modules/pdp_qt.c +++ b/modules/pdp_qt.c @@ -19,7 +19,6 @@ */ - #include "pdp.h" #include "pdp_llconv.h" #include <quicktime/lqt.h> @@ -169,8 +168,15 @@ static void pdp_qt_close(t_pdp_qt *x) void pdp_qt_create_pdp_packet(t_pdp_qt *x) { t_pdp *header; - int nbpixels = x->x_video_width * x->x_video_height; - //int packet_size = (x->x_qt_cmodel == BC_RGB888) ? (nbpixels << 1) : (nbpixels + (nbpixels >> 1)) << 1; + + + /* round to next legal size */ + /* if size is illegal, image distortion will occur */ + u32 w = pdp_imageproc_legalwidth(x->x_video_width); + u32 h = pdp_imageproc_legalheight(x->x_video_height); + + + int nbpixels = w * h; int packet_size = (nbpixels + (nbpixels >> 1)) << 1; @@ -180,8 +186,8 @@ void pdp_qt_create_pdp_packet(t_pdp_qt *x) //header->info.image.encoding = (x->x_qt_cmodel == BC_RGB888) ? PDP_IMAGE_GREY : PDP_IMAGE_YV12; header->info.image.encoding = PDP_IMAGE_YV12; - header->info.image.width = x->x_video_width; - header->info.image.height = x->x_video_height; + header->info.image.width = w; + header->info.image.height = h; } @@ -939,3 +945,5 @@ void pdp_qt_setup(void) #ifdef __cplusplus } #endif + + diff --git a/modules/pdp_sdl.c b/modules/pdp_sdl.c index 7bd8992..d30ef84 100644 --- a/modules/pdp_sdl.c +++ b/modules/pdp_sdl.c @@ -1,6 +1,6 @@ /* * Pure Data Packet module. - * Copyright (c) by martin pi <pi@attacksyour.net> + * Copyright (c) 2003 by martin pi <pi@attacksyour.net> * Copyright (c) by Tom Schouten <pdp@zzz.kotnet.org> * * This program is free software; you can redistribute it and/or modify @@ -33,16 +33,15 @@ TODO: */ - #include <stdio.h> -#include <unistd.h> -#include <sys/ipc.h> -#include <sys/shm.h> +//#include <unistd.h> +//#include <sys/ipc.h> +//#include <sys/shm.h> #include <SDL/SDL.h> -#include <quicktime/lqt.h> -#include <quicktime/colormodels.h> +//#include <quicktime/lqt.h> +//#include <quicktime/colormodels.h> #include "pdp.h" #include "pdp_llconv.h" @@ -52,8 +51,6 @@ TODO: #define PDP_SDL_W 320 #define PDP_SDL_H 240 -#define PDP_AUTOCREATE_RETRY 3 - typedef struct pdp_sdl_struct { t_object x_obj; @@ -65,6 +62,8 @@ typedef struct pdp_sdl_struct { SDL_Surface *x_sdl_surface; SDL_Overlay *x_sdl_overlay; SDL_Rect x_sdl_rect; + + int x_xid; Uint32 x_sdl_format; @@ -74,59 +73,69 @@ typedef struct pdp_sdl_struct { unsigned int x_width; unsigned int x_height; int x_last_encoding; + int x_cursor; int x_initialized; int x_backfromthread; - int x_autocreate; - int x_fullscreen; } t_pdp_sdl; -static SDL_Surface *pdp_sdl_getSurface(char* title, int width, int height, int bits, int fullscreenflag) { +static SDL_Surface *pdp_sdl_getSurface(int xid, char* title, int width, int height, int bits, int fullscreenflag, int cursorflag) { Uint32 flags; int size,i; SDL_Surface *screen; + char SDL_hack[32]; + + /* next lines from gstreamer plugin sdlvideosink */ + if (xid < 0) unsetenv("SDL_WINDOWID"); + else { + sprintf(SDL_hack, "%d", xid); + setenv("SDL_WINDOWID", SDL_hack, 1); + } /* Initialize SDL */ if (!SDL_WasInit(SDL_INIT_VIDEO)) { if (SDL_Init (SDL_INIT_VIDEO|SDL_INIT_NOPARACHUTE)) { - printf("SDL: Initializing of SDL failed: %s.\n", SDL_GetError()); - return (SDL_Surface *)-1; + post("SDL: Initializing of SDL failed: %s.\n", SDL_GetError()); + return NULL; } - } - + /* ignore events :: only keys and wm_quit */ + for ( i=SDL_NOEVENT; i<SDL_NUMEVENTS; ++i ) + if( !(i & (SDL_KEYDOWN|SDL_VIDEORESIZE)) ) + SDL_EventState(i, SDL_IGNORE); + + } /* gem : SDL_OPENGL|SDL_DOUBLEBUF|SDL_HWSURFACE|SDL_ANYFORMAT|SDL_OPENGLBLIT; working: SDL_ANYFORMAT|SDL_RESIZABLE|SDL_RLEACCEL; */ - - flags = SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL; + flags = SDL_SWSURFACE | SDL_RESIZABLE; +// flags = SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL|SDL_ANYFORMAT|SDL_RLEACCEL; if ( fullscreenflag>0 ) { flags |= SDL_FULLSCREEN|SDL_DOUBLEBUF; } - /* Have a preference for 8-bit, but accept any depth */ screen = SDL_SetVideoMode(width, height, bits, flags); if ( screen == NULL ) { - fprintf(stderr, "Couldn't set video mode: %s\n", - SDL_GetError()); + post("Couldn't set video mode: %s\n", SDL_GetError()); return NULL; } SDL_WM_SetCaption (title, title); - /* ignore events :: only keys and wm_quit */ - for ( i=SDL_NOEVENT; i<SDL_NUMEVENTS; ++i ) - if( !(i & (SDL_KEYDOWN|SDL_QUIT)) ) - SDL_EventState(i, SDL_IGNORE); + SDL_ShowCursor(cursorflag); - SDL_ShowCursor(1); + return screen; +} - return screen; // Success +static SDL_Surface *pdp_sdl_recreateSurface(SDL_Surface *old, int xid, char* title, int width, int height, int bits, int fullscreenflag, int cursorflag) { + SDL_Surface *new = pdp_sdl_getSurface(xid, title, width, height, bits, fullscreenflag, cursorflag); + if (new != NULL) SDL_FreeSurface(old); + return new; } static inline void pdp_sdl_getOverlay(t_pdp_sdl* x) { @@ -169,30 +178,26 @@ static int pdp_sdl_drawImage(t_pdp_sdl* x, t_image *image, short int *pixels) { return 1; } -static void pdp_sdl_resize(t_pdp_sdl* x, t_floatarg width, t_floatarg height) { +static void pdp_sdl_fullscreen(t_pdp_sdl *x, t_floatarg f); - if (x->x_initialized && (!x->x_fullscreen) && (width>0) && (height>0)){ -// disabled for now -// if media size is different to the one set, it will resize (yet never dither) - } +static inline void pdp_sdl_recreate(t_pdp_sdl *x) { + x->x_sdl_surface = pdp_sdl_recreateSurface(x->x_sdl_surface, x->x_xid,"pdp-sdl", x->x_winwidth, x->x_winheight, 16, x->x_fullscreen,x->x_cursor); } -static void pdp_sdl_fullscreen(t_pdp_sdl *x, t_floatarg f); - static int pdp_sdl_create(t_pdp_sdl *x) { if (x->x_initialized){ return 0; } x->x_initialized = 0; - x->x_sdl_surface = pdp_sdl_getSurface("pdp-sdl", x->x_winwidth, x->x_winheight, 16, x->x_fullscreen); + x->x_sdl_surface = pdp_sdl_getSurface(x->x_xid, "pdp-sdl", x->x_winwidth, x->x_winheight, 16, x->x_fullscreen,x->x_cursor); if (x->x_sdl_surface != NULL) { pdp_sdl_getOverlay(x); if (x->x_sdl_overlay != NULL) { x->x_sdl_rect.x = 0; x->x_sdl_rect.y = 0; - x->x_sdl_rect.w = x->x_width; - x->x_sdl_rect.h = x->x_height; + x->x_sdl_rect.w = x->x_winwidth; + x->x_sdl_rect.h = x->x_winheight; x->x_initialized = 1; post("created successfully"); } @@ -203,12 +208,13 @@ static int pdp_sdl_create(t_pdp_sdl *x) { } static void pdp_sdl_destroy(t_pdp_sdl *x); +static void pdp_sdl_resize(t_pdp_sdl *x,t_floatarg,t_floatarg); static void pdp_sdl_checkEvents(t_pdp_sdl *x) { Uint8 *keys; SDL_Event event; - if (!SDL_PollEvent(&event)) return; + if (SDL_PollEvent(&event)!=1) return; switch( event.type ){ case SDL_KEYDOWN: @@ -224,6 +230,9 @@ static void pdp_sdl_checkEvents(t_pdp_sdl *x) { case SDL_QUIT: pdp_sdl_destroy(x); break; + case SDL_VIDEORESIZE: + pdp_sdl_resize(x,(t_floatarg)event.resize.w,(t_floatarg)event.resize.h); + break; default: break; } @@ -231,26 +240,6 @@ static void pdp_sdl_checkEvents(t_pdp_sdl *x) { } -static int pdp_sdl_try_autocreate(t_pdp_sdl *x) -{ - - if (x->x_autocreate){ - post("pdp_sdl: autocreate window"); - pdp_sdl_create(x); - if (!(x->x_initialized)){ - x->x_autocreate--; - if (!x->x_autocreate){ - post ("pdp_sdl: autocreate failed %d times: disabled", PDP_AUTOCREATE_RETRY); - post ("pdp_sdl: send [autocreate 1] message to re-enable"); - return 0; - } - } - else return 1; - - } - return 0; -} - static void pdp_sdl_bang(t_pdp_sdl *x); static void pdp_sdl_process(t_pdp_sdl *x) @@ -263,8 +252,7 @@ static void pdp_sdl_process(t_pdp_sdl *x) /* check if window is initialized */ if (!(x->x_initialized)){ - post("trying to autocreate"); - if (!pdp_sdl_try_autocreate(x)) return; + if (!pdp_sdl_create(x)) return; } /* check for pending sdl events */ @@ -296,6 +284,7 @@ static void pdp_sdl_destroy(t_pdp_sdl *x) { pdp_sdl_freeOverlay(x); SDL_FreeSurface(x->x_sdl_surface); x->x_initialized = 0; + SDL_Quit(); } } @@ -309,10 +298,8 @@ static void pdp_sdl_random(t_pdp_sdl *x) { /* redisplays image */ static void pdp_sdl_bang_thread(t_pdp_sdl *x) { -// if (x->x_sdl_overlay->pixels) { - if (SDL_DisplayYUVOverlay(x->x_sdl_overlay, &(* x).x_sdl_rect) <0) - post("pdp_sdl: __LINE__ cannot display"); -// } + if (SDL_DisplayYUVOverlay(x->x_sdl_overlay, &(* x).x_sdl_rect) <0) + post("pdp_sdl: __LINE__ cannot display"); } static void pdp_sdl_bang_callback(t_pdp_sdl *x) @@ -340,34 +327,122 @@ static void pdp_sdl_input_0(t_pdp_sdl *x, t_symbol *s, t_floatarg f) { } -static void pdp_sdl_autocreate(t_pdp_sdl *x, t_floatarg f) { - if (f != 0.0f) x->x_autocreate = PDP_AUTOCREATE_RETRY; - else x->x_autocreate = 0; +static void pdp_sdl_resize(t_pdp_sdl* x, t_floatarg width, t_floatarg height) { + + if (x->x_initialized && (!x->x_fullscreen) && (width>0) && (height>0)) { + post("should get %d/%d",(int)width,(int) height); + x->x_winwidth=(int)width; + x->x_winheight=(int)height; + pdp_sdl_recreate(x); + } } + static void pdp_sdl_fullscreen(t_pdp_sdl *x, t_floatarg f) { if (f == x->x_fullscreen) return; - x->x_fullscreen = (f != 0.0f); + x->x_fullscreen = (f != 0.0f); + x->x_cursor=0; + + pdp_sdl_recreate(x); +} + +static void pdp_sdl_cursor(t_pdp_sdl *x, t_floatarg f) { + if (f == x->x_cursor) return; + + x->x_cursor = (f != 0.0f); + SDL_ShowCursor(x->x_cursor); +} + + +/* sets new target window */ + +static void pdp_sdl_win(t_pdp_sdl *x, t_floatarg *f) { + pdp_queue_finish(x->x_queue_id); + x->x_queue_id = -1; + x->x_xid = (int)f; + pdp_sdl_recreate(x); +} + +/* be very carefule not to set DGA fro here! */ +/* use export SDL_VIDEODRIVER=dga (or equivalent for your shell) instead */ + +static void pdp_sdl_renderer(t_pdp_sdl *x, t_symbol *s) { + char SDL_hack[32]; pdp_sdl_destroy(x); + + /* next lines from gstreamer plugin sdlvideosink */ + unsetenv("SDL_VIDEODRIVER"); + + sprintf(SDL_hack, "%s", s->s_name); + setenv("SDL_VIDEODRIVER", SDL_hack, 1); + pdp_sdl_create(x); - SDL_ShowCursor(0); } static void pdp_sdl_free(t_pdp_sdl *x) { - pdp_queue_finish(x->x_queue_id); - pdp_sdl_destroy(x); - pdp_packet_mark_unused(x->x_packet0); - SDL_Quit(); + pdp_queue_finish(x->x_queue_id); + pdp_sdl_destroy(x); + pdp_packet_mark_unused(x->x_packet0); +// SDL_Quit(); +} + +static void pdp_sdl_listmodes(const char* title, Uint32 flags) { + SDL_Rect ** modes; + int i; + + /* Get available modes */ + modes = SDL_ListModes(NULL, flags); + + /* Check is there are any modes available */ + if(modes == (SDL_Rect **)0){ + printf("%s : No modes available!", title); + return; + } + + /* Check if our resolution is restricted */ + if(modes == (SDL_Rect **)-1){ + post("%s : All resolutions available.", title); + } else { + /* Print valid modes */ + for(i=0;modes[i];++i) + post("%s : %d x %d", title, modes[i]->w, modes[i]->h); + } + +} + +static void pdp_sdl_modes(t_pdp_sdl *x) { + pdp_sdl_listmodes("FULL|HWSURF|||||||||||||||||||||||||", SDL_FULLSCREEN|SDL_HWSURFACE); + pdp_sdl_listmodes("HWSURF|RESIZ|ASYNC|HWACCEL||||||||||", SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL); + pdp_sdl_listmodes("HWSURF|RESIZ|ASYNC|HWACCEL|FULL|DBUF", SDL_HWSURFACE|SDL_RESIZABLE|SDL_ASYNCBLIT|SDL_HWACCEL|SDL_FULLSCREEN|SDL_DOUBLEBUF); + pdp_sdl_listmodes("OPENGL|DBUF|HWSURF|ANYF|GLBLIT||||||", SDL_OPENGL|SDL_DOUBLEBUF|SDL_HWSURFACE|SDL_ANYFORMAT|SDL_OPENGLBLIT); + pdp_sdl_listmodes("ANYF|RESIZ|RLEA|||||||||||||||||||||", SDL_ANYFORMAT|SDL_RESIZABLE|SDL_RLEACCEL); } +static void pdp_sdl_info(t_pdp_sdl *x) { + const SDL_VideoInfo *narf; + post("\nSDL video info: note that this only works under dga mode\n"); + narf = SDL_GetVideoInfo(); + post("Is it possible to create hardware surfaces?\t\thw_available=%d",narf->hw_available); + post("Is there a window manager available?\t\t\twm_available=%d",narf->wm_available); + post("Are hardware to hardware blits accelerated?\t\tblit_hw=%d",narf->blit_hw); + post("Are hardware to hardware colorkey blits accelerated?\tblit_hw_CC=%d",narf->blit_hw_CC); + post("Are hardware to hardware alpha bits accelerated?\tblit_hw_A=%d",narf->blit_hw_A); + post("Are software to hardware blits accelerated?\t\tblit_sw=%d",narf->blit_sw); + post("Are software to hardware colorkey blits accelerated?\tblit_sw_CC=%d",narf->blit_sw_CC); + post("Are software to hardware alpha blits accelerated?\tblit_sw_A=%d",narf->blit_sw_A); + post("Are color fills accelerated?\t\t\t\tblit_fill=%d",narf->blit_fill); + post("Total amount of video_mem: %d",narf->video_mem); + +} t_class *pdp_sdl_class; -void *pdp_sdl_new(void) -{ +void *pdp_sdl_new(void) { + + t_pdp_sdl *x = (t_pdp_sdl *)pd_new(pdp_sdl_class); x->x_packet0 = -1; @@ -385,9 +460,13 @@ void *pdp_sdl_new(void) x->x_backfromthread = 1; x->x_initialized = 0; - pdp_sdl_autocreate(x,1); - x->x_fullscreen = 0; + x->x_fullscreen = 0; + x->x_cursor=1; + + x->x_xid = -1; + + pdp_sdl_create(x); return (void *)x; } @@ -411,13 +490,16 @@ void pdp_sdl_setup(void) class_addmethod(pdp_sdl_class, (t_method)pdp_sdl_bang, gensym("bang"), A_NULL); class_addmethod(pdp_sdl_class, (t_method)pdp_sdl_random, gensym("random"), A_NULL); class_addmethod(pdp_sdl_class, (t_method)pdp_sdl_create, gensym("create"), A_NULL); - class_addmethod(pdp_sdl_class, (t_method)pdp_sdl_autocreate, gensym("autocreate"), A_FLOAT, A_NULL); + class_addmethod(pdp_sdl_class, (t_method)pdp_sdl_info, gensym("info"), A_NULL); + class_addmethod(pdp_sdl_class, (t_method)pdp_sdl_modes, gensym("modes"), A_NULL); class_addmethod(pdp_sdl_class, (t_method)pdp_sdl_destroy, gensym("destroy"), A_NULL); class_addmethod(pdp_sdl_class, (t_method)pdp_sdl_destroy, gensym("close"), A_NULL); -// class_addmethod(pdp_sdl_class, (t_method)pdp_sdl_resize, gensym("dim"), A_FLOAT, A_FLOAT, A_NULL); -// class_addmethod(pdp_sdl_class, (t_method)pdp_sdl_resize, gensym("size"), A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(pdp_sdl_class, (t_method)pdp_sdl_resize, gensym("dim"), A_FLOAT, A_FLOAT, A_NULL); + class_addmethod(pdp_sdl_class, (t_method)pdp_sdl_resize, gensym("size"), A_FLOAT, A_FLOAT, A_NULL); class_addmethod(pdp_sdl_class, (t_method)pdp_sdl_fullscreen, gensym("fullscreen"), A_FLOAT, A_NULL); -// class_addmethod(pdp_sdl_class, (t_method)pdp_sdl_display, gensym("display"), A_SYMBOL, A_NULL); + class_addmethod(pdp_sdl_class, (t_method)pdp_sdl_cursor, gensym("cursor"), A_FLOAT, A_NULL); + class_addmethod(pdp_sdl_class, (t_method)pdp_sdl_win, gensym("window"), A_FLOAT, A_NULL); + class_addmethod(pdp_sdl_class, (t_method)pdp_sdl_renderer, gensym("renderer"), A_SYMBOL, A_NULL); class_addmethod(pdp_sdl_class, (t_method)pdp_sdl_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); } @@ -425,3 +507,4 @@ void pdp_sdl_setup(void) #ifdef __cplusplus } #endif + diff --git a/modules/pdp_v4l.c b/modules/pdp_v4l.c index e4dbff9..f1195c3 100644 --- a/modules/pdp_v4l.c +++ b/modules/pdp_v4l.c @@ -19,9 +19,10 @@ */ - +#include "pdp_config.h" #include "pdp.h" #include "pdp_llconv.h" +#include "pdp_imageproc.h" #include <stdio.h> #include <stdlib.h> #include <stdarg.h> @@ -45,9 +46,7 @@ // is reset when manually opened or closed #define PDP_XV_RETRIES 10 -//uncomment this for additional philips webcam control -//#define HAVE_V4LPWC -#ifdef HAVE_V4LPWC +#ifdef HAVE_PWCV4L #include "pwc-ioctl.h" #endif @@ -107,6 +106,11 @@ typedef struct pdp_v4l_struct int x_open_retry; + u32 x_minwidth; + u32 x_maxwidth; + u32 x_minheight; + u32 x_maxheight; + } t_pdp_v4l; @@ -158,7 +162,7 @@ static void pdp_v4l_pwc_init(t_pdp_v4l *x) { /* todo add detection code for pwc */ -#ifdef HAVE_V4LPWC +#ifdef HAVE_PWCV4L if(ioctl(x->x_tvfd, VIDIOCPWCRUSER)){ perror("pdp_v4l: pwc: VIDIOCPWCRUSER"); @@ -259,6 +263,7 @@ static void *pdp_v4l_thread(void *voidx) return 0; } +static void pdp_v4l_setlegaldim(t_pdp_v4l *x, int xx, int yy); static void pdp_v4l_open(t_pdp_v4l *x, t_symbol *name) { @@ -302,6 +307,12 @@ static void pdp_v4l_open(t_pdp_v4l *x, t_symbol *name) post("pdp_v4l: cap: name %s type %d channels %d maxw %d maxh %d minw %d minh %d", x->x_vcap.name, x->x_vcap.type, x->x_vcap.channels, x->x_vcap.maxwidth, x->x_vcap.maxheight, x->x_vcap.minwidth, x->x_vcap.minheight); + + x->x_minwidth = pdp_imageproc_legalwidth(x->x_vcap.minwidth); + x->x_maxwidth = pdp_imageproc_legalwidth_round_down(x->x_vcap.maxwidth); + x->x_minheight = pdp_imageproc_legalheight(x->x_vcap.minheight); + x->x_maxheight = pdp_imageproc_legalheight_round_down(x->x_vcap.maxheight); + if (ioctl(x->x_tvfd, VIDIOCGPICT, &x->x_vpicture) < 0) { @@ -376,10 +387,9 @@ static void pdp_v4l_open(t_pdp_v4l *x, t_symbol *name) goto closit; } - width = (x->x_width > (unsigned int)x->x_vcap.minwidth) ? x->x_width : (unsigned int)x->x_vcap.minwidth; - width = (width > (unsigned int)x->x_vcap.maxwidth) ?(unsigned int) x->x_vcap.maxwidth : width; - height = (x->x_height > (unsigned int)x->x_vcap.minheight) ? x->x_height :(unsigned int) x->x_vcap.minheight; - height = (height > (unsigned int)x->x_vcap.maxheight) ? (unsigned int)x->x_vcap.maxheight : height; + pdp_v4l_setlegaldim(x, x->x_width, x->x_height); + width = x->x_width; + height = x->x_height; for (i = 0; i < NBUF; i++) { @@ -633,27 +643,34 @@ static void pdp_v4l_bang(t_pdp_v4l *x) } -static void pdp_v4l_dim(t_pdp_v4l *x, t_floatarg xx, t_floatarg yy) +static void pdp_v4l_setlegaldim(t_pdp_v4l *x, int xx, int yy) { - unsigned int w,h; - xx = (xx < 0.0f) ? 0.0f : xx; - yy = (yy < 0.0f) ? 0.0f : yy; + unsigned int w,h; - w = (unsigned int)xx; - h = (unsigned int)yy; + w = pdp_imageproc_legalwidth((int)xx); + h = pdp_imageproc_legalheight((int)yy); + + w = (w < x->x_maxwidth) ? w : x->x_maxwidth; + w = (w > x->x_minwidth) ? w : x->x_minwidth; + h = (h < x->x_maxheight) ? h : x->x_maxheight; + h = (h > x->x_minheight) ? h : x->x_minheight; - if (x->x_initialized){ - pdp_v4l_close(x); x->x_width = w; x->x_height = h; +} + +static void pdp_v4l_dim(t_pdp_v4l *x, t_floatarg xx, t_floatarg yy) +{ + if (x->x_initialized){ + pdp_v4l_close(x); + pdp_v4l_setlegaldim(x, (int)xx, (int)yy); pdp_v4l_open(x, x->x_device); } else{ - x->x_width = w; - x->x_height = h; + pdp_v4l_setlegaldim(x, (int)xx, (int)yy); } } @@ -699,6 +716,12 @@ void *pdp_v4l_new(void) x->x_channel = 0; x->x_freq = -1; //don't set freq by default + x->x_minwidth = pdp_imageproc_legalwidth(0); + x->x_maxwidth = pdp_imageproc_legalwidth_round_down(0x7fffffff); + x->x_minheight = pdp_imageproc_legalheight(0); + x->x_maxheight = pdp_imageproc_legalheight_round_down(0x7fffffff); + + return (void *)x; } diff --git a/modules/pdp_xv.c b/modules/pdp_xv.c index c859a40..fde5409 100644 --- a/modules/pdp_xv.c +++ b/modules/pdp_xv.c @@ -24,9 +24,9 @@ pdp xvideo output */ - // x stuff #include <X11/Xlib.h> +#include <X11/Xatom.h> #include <X11/extensions/Xv.h> #include <X11/extensions/Xvlib.h> @@ -51,6 +51,7 @@ typedef struct pdp_xv_struct { t_object x_obj; t_float x_f; + t_outlet *x_outlet; int x_packet0; int x_queue_id; @@ -60,6 +61,7 @@ typedef struct pdp_xv_struct int x_screen; Window x_win; GC x_gc; + Atom x_WM_DELETE_WINDOW; int x_xv_format; int x_xv_port; @@ -77,6 +79,7 @@ typedef struct pdp_xv_struct int x_autocreate; float x_cursor; + t_symbol *x_dragbutton; } t_pdp_xv; @@ -122,10 +125,12 @@ void pdp_xv_create_xvimage(t_pdp_xv *x) { long size = (x->x_width * x->x_height + (((x->x_width>>1)*(x->x_height>>1))<<1)); + //post("create xvimage %d %d", x->x_width, x->x_height); x->x_data = (unsigned char *)malloc(size); x->x_xvi = XvCreateImage(x->x_dpy, x->x_xv_port, x->x_xv_format, (char *)x->x_data, x->x_width, x->x_height); x->x_last_encoding = -1; - if (!(x->x_xvi) || (!x->x_data)) post ("ERROR CREATING XVIMAGE"); + if ((!x->x_xvi) || (!x->x_data)) post ("ERROR CREATING XVIMAGE"); + //post("created xvimag data:%x xvi:%x",x->x_data,x->x_xvi); } @@ -193,6 +198,7 @@ static void pdp_xv_create(t_pdp_xv* x) XEvent e; unsigned int i; + if( x->x_initialized ){ //post("pdp_xv: window already created"); return; @@ -230,6 +236,11 @@ static void pdp_xv_create(t_pdp_xv* x) BlackPixel(x->x_dpy, x->x_screen), BlackPixel(x->x_dpy, x->x_screen)); + + /* enable handling of close window event */ + x->x_WM_DELETE_WINDOW = XInternAtom(x->x_dpy, "WM_DELETE_WINDOW", True); + (void)XSetWMProtocols(x->x_dpy, x->x_win, &x->x_WM_DELETE_WINDOW, 1); + if(!(x->x_win)){ /* clean up mess */ post("pdp_xv: could not create window\n"); @@ -243,7 +254,10 @@ static void pdp_xv_create(t_pdp_xv* x) return; } - XSelectInput(x->x_dpy, x->x_win, StructureNotifyMask); + /* select input events */ + XSelectInput(x->x_dpy, x->x_win, StructureNotifyMask + | ButtonPressMask | ButtonReleaseMask | MotionNotify | ButtonMotionMask); + XMapWindow(x->x_dpy, x->x_win); @@ -255,7 +269,10 @@ static void pdp_xv_create(t_pdp_xv* x) } + /* we're done initializing */ x->x_initialized = true; + + /* disable/enable cursor */ pdp_xv_cursor(x, x->x_cursor); } @@ -380,31 +397,104 @@ static void pdp_xv_random(t_pdp_xv *x) for(i=0; i<x->x_width*x->x_height/4; i++) intdata[i]=random(); } + /* redisplays image */ static void pdp_xv_bang_thread(t_pdp_xv *x) { - XEvent e; unsigned int i; + XEvent e; + XConfigureEvent *ce = (XConfigureEvent *)&e; + XButtonEvent *be = (XButtonEvent *)&e; + XMotionEvent *me = (XMotionEvent *)&e; + float inv_x, inv_y; + t_symbol *s; + t_atom atom[2]; + char nextdrag[]="drag0"; + char b='0'; + + inv_x = 1.0f / (float)(x->x_winwidth); + inv_y = 1.0f / (float)(x->x_winheight); - //while (XEventsQueued(x->x_dpy, QueuedAlready)){ while (XPending(x->x_dpy)){ - //post("pdp_xv: waiting for event"); + XNextEvent(x->x_dpy, &e); - //post("pdp_xv: XEvent %d", e.type); - if(e.type == ConfigureNotify){ - XConfigureEvent *ce = (XConfigureEvent *)&e; + + switch(e.type){ + case ConfigureNotify: x->x_winwidth = ce->width; x->x_winheight = ce->height; + inv_x = 1.0f / (float)(x->x_winwidth); + inv_y = 1.0f / (float)(x->x_winheight); + break; + + case ClientMessage: + if ((Atom)e.xclient.data.l[0] == x->x_WM_DELETE_WINDOW) { + post("pdp_xv: button disabled, please send a \"close\" message to close the window"); + //destroy = 1; + } + break; + + case ButtonPress: + //post("pdp_xv: press %f %f", inv_x * (float)be->x, inv_y * (float)be->y); + SETFLOAT(atom+0,inv_x * (float)be->x); + SETFLOAT(atom+1,inv_y * (float)be->y); + outlet_anything(x->x_outlet, gensym("press"), 2, atom); + switch(be->button){ + case Button1: outlet_anything(x->x_outlet, gensym("press1"), 2, atom); b='1'; break; + case Button2: outlet_anything(x->x_outlet, gensym("press2"), 2, atom); b='2'; break; + case Button3: outlet_anything(x->x_outlet, gensym("press3"), 2, atom); b='3'; break; + case Button4: outlet_anything(x->x_outlet, gensym("press4"), 2, atom); b='4'; break; + case Button5: outlet_anything(x->x_outlet, gensym("press5"), 2, atom); b='5'; break; + default: break; + } + nextdrag[4]=b; + x->x_dragbutton = gensym(nextdrag); + break; + + case ButtonRelease: + //post("pdp_xv: release %f %f", inv_x * (float)be->x, inv_y * (float)be->y); + SETFLOAT(atom+0,inv_x * (float)be->x); + SETFLOAT(atom+1,inv_y * (float)be->y); + outlet_anything(x->x_outlet, gensym("release"), 2, atom); + switch(be->button){ + case Button1: outlet_anything(x->x_outlet, gensym("release1"), 2, atom); break; + case Button2: outlet_anything(x->x_outlet, gensym("release2"), 2, atom); break; + case Button3: outlet_anything(x->x_outlet, gensym("release3"), 2, atom); break; + case Button4: outlet_anything(x->x_outlet, gensym("release4"), 2, atom); break; + case Button5: outlet_anything(x->x_outlet, gensym("release5"), 2, atom); break; + default: break; + } + break; + case MotionNotify: + //post("pdp_xv: drag %f %f", inv_x * (float)be->x, inv_y * (float)be->y); + SETFLOAT(atom+0,inv_x * (float)be->x); + SETFLOAT(atom+1,inv_y * (float)be->y); + outlet_anything(x->x_outlet, gensym("drag"), 2, atom); + outlet_anything(x->x_outlet, x->x_dragbutton, 2, atom); + break; + + default: + //post("pdp_xv: unknown event"); + break; } - //post("pdp_xv: received event"); } + // THIS SEEMS TO CRASH ON VERY LARGE IMAGES.. + //post("start"); + //post("XvPutImage xvi:%x",x->x_xvi); XvPutImage(x->x_dpy,x->x_xv_port,x->x_win,x->x_gc,x->x_xvi, 0,0,x->x_width,x->x_height, 0,0,x->x_winwidth,x->x_winheight); + //post("XFlush"); XFlush(x->x_dpy); + + //post("end"); + + + + } static void pdp_xv_bang_callback(t_pdp_xv *x) @@ -416,6 +506,11 @@ static void pdp_xv_bang_callback(t_pdp_xv *x) static void pdp_xv_bang(t_pdp_xv *x) { + /* check if window is initialized */ + if (!(x->x_initialized)){ + if (!pdp_xv_try_autocreate(x)) return; + } + /* if previous queued method returned schedule a new one, else ignore */ @@ -434,6 +529,11 @@ static void pdp_xv_input_0(t_pdp_xv *x, t_symbol *s, t_floatarg f) } +static void pdp_xv_vga(t_pdp_xv *x) +{ + pdp_xv_resize(x, 640, 480); +} + static void pdp_xv_autocreate(t_pdp_xv *x, t_floatarg f) { if (f != 0.0f) x->x_autocreate = PDP_XV_AUTOCREATE_RETRY; @@ -468,6 +568,7 @@ t_class *pdp_xv_class; void *pdp_xv_new(void) { t_pdp_xv *x = (t_pdp_xv *)pd_new(pdp_xv_class); + x->x_outlet = outlet_new(&x->x_obj, &s_anything); x->x_packet0 = -1; @@ -495,12 +596,17 @@ void *pdp_xv_new(void) x->x_last_encoding = -1; x->x_cursor = 0; + x->x_dragbutton = gensym("drag1"); + + //pdp_xv_create(x); return (void *)x; } + + #ifdef __cplusplus extern "C" { @@ -517,6 +623,7 @@ void pdp_xv_setup(void) class_addmethod(pdp_xv_class, (t_method)pdp_xv_bang, gensym("bang"), A_NULL); class_addmethod(pdp_xv_class, (t_method)pdp_xv_random, gensym("random"), A_NULL); + class_addmethod(pdp_xv_class, (t_method)pdp_xv_create, gensym("open"), A_NULL); class_addmethod(pdp_xv_class, (t_method)pdp_xv_create, gensym("create"), A_NULL); class_addmethod(pdp_xv_class, (t_method)pdp_xv_autocreate, gensym("autocreate"), A_FLOAT, A_NULL); class_addmethod(pdp_xv_class, (t_method)pdp_xv_destroy, gensym("destroy"), A_NULL); @@ -527,8 +634,13 @@ void pdp_xv_setup(void) class_addmethod(pdp_xv_class, (t_method)pdp_xv_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL); class_addmethod(pdp_xv_class, (t_method)pdp_xv_cursor, gensym("cursor"), A_FLOAT, A_NULL); + /* some shortcuts for the lazy */ + class_addmethod(pdp_xv_class, (t_method)pdp_xv_vga, gensym("vga"), A_NULL); + } #ifdef __cplusplus } #endif + + |