aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.LOG3
-rw-r--r--Makefile.in7
-rw-r--r--configure.ac8
-rwxr-xr-xdoc/pdp_vloopback-help.pd75
-rwxr-xr-xmodules/pdp_vloopback.c338
-rw-r--r--system/pidip.c2
6 files changed, 426 insertions, 7 deletions
diff --git a/CHANGES.LOG b/CHANGES.LOG
index e2528b9..7eec7ce 100644
--- a/CHANGES.LOG
+++ b/CHANGES.LOG
@@ -1,3 +1,6 @@
+0.12.25 ( codename Dangerous Modules )
+ added pdp_vloopback : some say it's dangerous, but it works smooth
+
0.12.25 ( codename CrunchyBits )
fixed default font for pdp_text, pdp_qtext
fixed crash in pdp_theonice~
diff --git a/Makefile.in b/Makefile.in
index 9b5af14..df125d3 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -14,7 +14,6 @@ MPEG4IP_CFLAGS = @MPEG4IP_CFLAGS@
PDP_PIDIP_DISTRO = /mnt/c/ydegoyon.free.fr/pidip-$(PDP_PIDIP_VERSION)
PDP_PIDIP_TARBALL = $(PDP_PIDIP_DISTRO).tar.gz
-
PDP_PIDIP_CFLAGS = $(MPEG4IP_CFLAGS) $(IMLIB_CFLAGS) \
-DPD -DX_DISPLAY_MISSING -O2 -funroll-loops -fomit-frame-pointer -ffast-math \
-fPIC -Wall -W -Wstrict-prototypes \
@@ -29,10 +28,12 @@ PDP_PIDIP_CPPFLAGS = $(MPEG4IP_CFLAGS) $(IMLIB_CFLAGS) \
ifeq ($(shell uname -s),Darwin)
all: pidip.pd_darwin
+PDP_PIDIP_SFLAGS = -D__OSX__
endif
ifeq ($(shell uname -s),Linux)
all: pidip.pd_linux
+PDP_PIDIP_SFLAGS = -D__LINUX__
endif
pdp_pidip_all:
@@ -67,7 +68,7 @@ distro: clean all
rm -rf /tmp/pidip-$(PDP_PIDIP_VERSION)
.c.o:
- gcc $(PDP_PIDIP_INCLUDES) $(PDP_PIDIP_CFLAGS) -o $*.o -c $*.c
+ gcc $(PDP_PIDIP_INCLUDES) $(PDP_PIDIP_CFLAGS) $(PDP_PIDIP_SFLAGS) -o $*.o -c $*.c
.cpp.o:
- g++ $(PDP_PIDIP_INCLUDES) $(PDP_PIDIP_CPPFLAGS) -o $*.o -c $*.cpp
+ g++ $(PDP_PIDIP_INCLUDES) $(PDP_PIDIP_CPPFLAGS) $(PDP_PIDIP_SFLAGS) -o $*.o -c $*.cpp
diff --git a/configure.ac b/configure.ac
index 00739be..f9cec5a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@ AC_INIT
AC_CANONICAL_HOST
AC_CONFIG_HEADER(include/pidip_config.h)
-PDP_PIDIP_VERSION="0.12.25"
+PDP_PIDIP_VERSION="0.12.26"
PD_DIR=/usr/local/pd
PDP_DIR=/usr/local/pd/pdp
FFMPEG_SOURCE_DIR=/SOURCES/ffmpeg
@@ -240,9 +240,9 @@ then
fi
AC_CHECK_HEADER(linux/videodev2.h,
- PDP_CAPTURE_OBJECT="$PDP_CAPTURE_OBJECT pdp_v4l2.o"
- AC_DEFINE(HAVE_V4L2, 1, build pdp_v4l2),
- echo " linux/videodev2.h not found: not building pdp_v4l2")
+ PDP_CAPTURE_OBJECT="$PDP_CAPTURE_OBJECT pdp_v4l2.o pdp_vloopback.o"
+ AC_DEFINE(HAVE_V4L2, 1, build pdp_v4l2 and pdp_vloopback),
+ echo " linux/videodev2.h not found: not building pdp_v4l2 and pdp_vloopback")
case "$host" in
*-linux* )
diff --git a/doc/pdp_vloopback-help.pd b/doc/pdp_vloopback-help.pd
new file mode 100755
index 0000000..62a84ae
--- /dev/null
+++ b/doc/pdp_vloopback-help.pd
@@ -0,0 +1,75 @@
+#N canvas 261 169 712 664 10;
+#X obj 159 72 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1
+-1;
+#X msg 217 112 open \$1;
+#X obj 216 88 openpanel;
+#X obj 201 71 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1
+-1;
+#X msg 124 70 stop;
+#X obj 164 178 dac~;
+#X obj 147 112 metro 70;
+#X obj 142 144 pdp_yqt;
+#X obj 296 139 pdp_v4l;
+#X obj 305 108 metro 70;
+#X obj 350 74 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1
+-1;
+#X msg 307 75 stop;
+#X obj 511 446 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0
+1;
+#X obj 511 498 pdp_control;
+#X msg 511 471 thread \$1;
+#X floatatom 511 559 5 0 0 0 - - -;
+#X obj 511 530 route pdp_drop;
+#X obj 217 375 pdp_vloopback /dev/video1;
+#X obj 66 71 loadbang;
+#X msg 369 79 open /dev/video0;
+#X obj 505 110 metro 70;
+#X obj 550 76 bng 15 250 50 0 empty empty empty 20 8 0 8 -262144 -1
+-1;
+#X msg 507 77 stop;
+#X msg 569 81 open /dev/video0;
+#X text 99 453 pdp_vloopback : a vloopback output module;
+#X text 99 465 enables you to send pd output to any other application
+that supports v4l input ( skype \, webcamstudio \, ... );
+#X text 103 517 written by ydegoyon@gmail.com;
+#X text 101 504 code inspired by mjpegtools_yuv_to_v4l by Jan Panteltje
+;
+#X obj 497 141 pdp_v4l2 /dev/video0;
+#X msg 66 97 loop 1;
+#X obj 217 409 pdp_xv;
+#X text 382 374 default /dev/video1;
+#X msg 357 306 open /dev/video1;
+#X msg 359 334 close;
+#X text 464 304 open a vloopback device;
+#X text 400 334 close a vloopback device;
+#X floatatom 369 410 5 0 0 0 - - -;
+#X text 411 407 number of frames written;
+#X connect 0 0 6 0;
+#X connect 1 0 7 0;
+#X connect 2 0 1 0;
+#X connect 3 0 2 0;
+#X connect 4 0 6 0;
+#X connect 6 0 7 0;
+#X connect 7 0 17 0;
+#X connect 7 4 5 0;
+#X connect 7 5 5 1;
+#X connect 8 0 17 0;
+#X connect 9 0 8 0;
+#X connect 10 0 9 0;
+#X connect 11 0 9 0;
+#X connect 12 0 14 0;
+#X connect 13 0 16 0;
+#X connect 14 0 13 0;
+#X connect 16 0 15 0;
+#X connect 17 0 30 0;
+#X connect 17 1 36 0;
+#X connect 18 0 29 0;
+#X connect 19 0 8 0;
+#X connect 20 0 28 0;
+#X connect 21 0 20 0;
+#X connect 22 0 20 0;
+#X connect 23 0 28 0;
+#X connect 28 0 17 0;
+#X connect 29 0 7 0;
+#X connect 32 0 17 0;
+#X connect 33 0 17 0;
diff --git a/modules/pdp_vloopback.c b/modules/pdp_vloopback.c
new file mode 100755
index 0000000..12f9e31
--- /dev/null
+++ b/modules/pdp_vloopback.c
@@ -0,0 +1,338 @@
+/*
+ * PiDiP module
+ * Authors : Yves Degoyon ( ydegoyon@free.fr ) and Lluis Gomez i Bigorda
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/* This object is a vloopback output module,
+ * inspired by the code of mjpegtools_yuv_to_v4l by Jan Panteltje
+ * it enables you to send pd output to another application
+ * that supports v4l input
+ */
+
+
+#include "pdp_config.h"
+#include "pdp.h"
+#include "pdp_imageproc.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <linux/types.h>
+#include <linux/videodev.h>
+
+typedef struct pdp_vloopback_struct
+{
+ t_object x_obj;
+ t_float x_f;
+
+ t_symbol *x_device;
+ int x_vlfd;
+
+ int x_packet0;
+ int x_packet1;
+ int x_dropped;
+ int x_queue_id;
+
+ t_outlet *x_outlet0;
+ t_outlet *x_outlet1;
+
+ int x_nbframes;
+
+ struct video_window x_vidwin;
+ struct video_picture x_vidpic;
+
+ bool x_initialized;
+
+ unsigned int x_width;
+ unsigned int x_height;
+
+} t_pdp_vloopback;
+
+static void pdp_vloopback_close(t_pdp_vloopback *x)
+{
+ // close the vloopback device
+ if ( close( x->x_vlfd ) == -1 )
+ {
+ post( "could not close device %s", x->x_device->s_name );
+ perror( "closing device" );
+ }
+ else
+ {
+ post( "closed device %s", x->x_device->s_name );
+ }
+
+ x->x_initialized=0;
+ x->x_nbframes=0;
+
+}
+
+static void pdp_vloopback_open(t_pdp_vloopback *x, t_symbol *name)
+{
+ // open a vloopback device and allocate buffers
+
+ // check if the vloopback module is loaded
+ // it might be the one of webcamstudio called webcamstudio
+ int module_loaded=0;
+ int ret;
+
+ x->x_device=name;
+
+#ifdef __LINUX__
+
+ if ( ( ret = system( "/sbin/lsmod | grep vloopback" ) ) == 256 )
+ {
+ post( "pdp_vloopback : vloopback module is not loaded (ret=%d)", ret );
+ }
+ else
+ {
+ post( "pdp_vloopback : vloopback module is loaded" );
+ module_loaded=1;
+ }
+
+ if ( ( ret = system( "/sbin/lsmod | grep webcamstudio" ) ) == 256 )
+ {
+ post( "pdp_vloopback : webcamstudio module is not loaded (ret=%d)", ret );
+ }
+ else
+ {
+ post( "pdp_vloopback : alternate module webcamstudio is loaded" );
+ module_loaded=1;
+ }
+
+ if ( module_loaded==0 )
+ {
+ post( "pdp_vloopback : refusing to proceed" );
+ return;
+ }
+
+#endif
+
+ if ( x->x_initialized )
+ {
+ pdp_vloopback_close(x);
+ }
+
+ // open the device
+ if ( ( x->x_vlfd = open (name->s_name, O_RDWR) ) < 0 )
+ {
+ post( "pdp_vloopback : unable to open : %s", name->s_name );
+ perror( "open device" );
+ return;
+ }
+
+ // setting palette to RGB24
+ if( ioctl(x->x_vlfd, VIDIOCGPICT, &x->x_vidpic) == -1)
+ {
+ post("pdp_vloopback : could get palette ( VIDIOCGPICT )");
+ perror( "ioctl VIDIOCGPICT" );
+ return;
+ }
+
+ x->x_vidpic.palette = VIDEO_PALETTE_RGB24;
+ if( ioctl(x->x_vlfd, VIDIOCSPICT, &x->x_vidpic) == -1)
+ {
+ post("pdp_vloopback : could set palette ( VIDIOCSPICT )");
+ perror( "ioctl VIDIOCSPICT" );
+ return;
+ }
+
+ // setting window size
+ if(ioctl (x->x_vlfd, VIDIOCGWIN, &x->x_vidwin) == -1)
+ {
+ post("pdp_vloopback : could get dimensions ( VIDIOCGWIN )");
+ perror( "ioctl VIDIOCGWIN" );
+ return;
+ }
+
+ x->x_vidwin.width = x->x_width;
+ x->x_vidwin.height = x->x_height;
+
+ if(ioctl (x->x_vlfd, VIDIOCSWIN, &x->x_vidwin) == -1)
+ {
+ post("pdp_vloopback : could set dimensions ( VIDIOCSWIN )");
+ perror( "ioctl VIDIOCSWIN" );
+ return;
+ }
+
+ // all went well we are now initialized
+ x->x_initialized=1;
+ post( "pdp_vloopback : opened device : %s", x->x_device->s_name );
+
+}
+
+static void pdp_vloopback_setlegaldim(t_pdp_vloopback *x, int xx, int yy)
+{
+ x->x_width = pdp_imageproc_legalwidth((int)xx);
+ x->x_height = pdp_imageproc_legalheight((int)yy);
+}
+
+static void pdp_vloopback_dim(t_pdp_vloopback *x, t_floatarg xx, t_floatarg yy)
+{
+ pdp_vloopback_setlegaldim(x, (int)xx, (int)yy);
+ if (x->x_initialized){
+ pdp_vloopback_close(x);
+ }
+ pdp_vloopback_open(x, x->x_device);
+}
+
+static void pdp_vloopback_process_rgb(t_pdp_vloopback *x)
+{
+ t_pdp *header = pdp_packet_header(x->x_packet0);
+ char *data = (char *)pdp_packet_data(x->x_packet0);
+ int written, flength;
+
+ if ( !x->x_initialized )
+ {
+ post( "pdp_vloopback : no vloopback device opened" );
+ return;
+ }
+
+ if ( (header->info.image.width != x->x_width ) ||
+ (header->info.image.height != x->x_height ) )
+ {
+ pdp_vloopback_dim(x, header->info.image.width, header->info.image.height);
+ }
+
+ // output the image
+ flength = x->x_width*x->x_height*3;
+
+ if ( ( written = write(x->x_vlfd, data, flength) ) != flength )
+ {
+ post( "pdp_vloopback : problem writing frame...closing" );
+ post( "pdp_vloopback : wrote %d bytes out of %d", written, flength );
+ }
+ else
+ {
+ outlet_float( x->x_outlet1, x->x_nbframes++);
+ }
+
+}
+
+static void pdp_vloopback_sendpacket(t_pdp_vloopback *x)
+{
+ /* release the packet */
+ pdp_packet_mark_unused(x->x_packet0);
+
+ /* unregister and propagate if valid dest packet */
+ pdp_packet_pass_if_valid(x->x_outlet0, &x->x_packet0);
+}
+
+static void pdp_vloopback_process(t_pdp_vloopback *x)
+{
+ int encoding;
+ t_pdp *header = 0;
+
+ /* check if image data packets are compatible */
+ if ( (header = pdp_packet_header(x->x_packet0))
+ && (PDP_BITMAP == header->type)){
+
+ /* pdp_vloopback_process inputs and write into active inlet */
+ switch(pdp_packet_header(x->x_packet0)->info.image.encoding){
+
+ case PDP_BITMAP_RGB:
+ pdp_queue_add(x, pdp_vloopback_process_rgb, pdp_vloopback_sendpacket, &x->x_queue_id);
+ break;
+
+ default:
+ /* don't know the type, so dont pdp_vloopback_process */
+ break;
+
+ }
+ }
+}
+
+static void pdp_vloopback_input_0(t_pdp_vloopback *x, t_symbol *s, t_floatarg f)
+{
+ /* if this is a register_ro message or register_rw message, register with packet factory */
+
+ if (s== gensym("register_rw"))
+ x->x_dropped = pdp_packet_convert_ro_or_drop(&x->x_packet0, (int)f, pdp_gensym("bitmap/rgb/*") );
+
+ if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped)){
+
+ /* add the process method and callback to the process queue */
+ pdp_vloopback_process(x);
+
+ }
+}
+
+static void pdp_vloopback_free(t_pdp_vloopback *x)
+{
+ pdp_vloopback_close(x);
+}
+
+t_class *pdp_vloopback_class;
+
+void *pdp_vloopback_new(t_symbol *vdev)
+{
+ t_pdp_vloopback *x = (t_pdp_vloopback *)pd_new(pdp_vloopback_class);
+
+ x->x_outlet0 = outlet_new(&x->x_obj, &s_anything);
+ x->x_outlet1 = outlet_new(&x->x_obj, &s_float);
+
+ x->x_initialized = false;
+ x->x_nbframes = 0;
+
+ x->x_packet0 = -1;
+ x->x_packet1 = -1;
+ x->x_queue_id = -1;
+
+ x->x_width = 320;
+ x->x_height = 240;
+
+ x->x_vlfd = -1;
+ if (vdev != gensym("")){
+ x->x_device = vdev;
+ pdp_vloopback_open(x, x->x_device);
+ }
+ else
+ {
+ x->x_device = gensym("/dev/video1");
+ }
+
+ return (void *)x;
+}
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+void pdp_vloopback_setup(void)
+{
+ pdp_vloopback_class = class_new(gensym("pdp_vloopback"), (t_newmethod)pdp_vloopback_new,
+ (t_method)pdp_vloopback_free, sizeof(t_pdp_vloopback), CLASS_DEFAULT, A_DEFSYMBOL, A_DEFSYMBOL, A_NULL);
+
+ class_addmethod(pdp_vloopback_class, (t_method)pdp_vloopback_close, gensym("close"), A_NULL);
+ class_addmethod(pdp_vloopback_class, (t_method)pdp_vloopback_open, gensym("open"), A_SYMBOL, A_NULL);
+ class_addmethod(pdp_vloopback_class, (t_method)pdp_vloopback_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
+
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/system/pidip.c b/system/pidip.c
index e51ba26..5e6a181 100644
--- a/system/pidip.c
+++ b/system/pidip.c
@@ -88,6 +88,7 @@ extern "C"
#ifdef HAVE_V4L2
void pdp_v4l2_setup(void);
+ void pdp_vloopback_setup(void);
#endif
#ifdef HAVE_LIBDV
@@ -195,6 +196,7 @@ void pidip_setup(void){
#ifdef HAVE_V4L2
pdp_v4l2_setup();
+ pdp_vloopback_setup();
#endif
#ifdef HAVE_LIBDV