aboutsummaryrefslogtreecommitdiff
path: root/modules/pdp_rec~.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/pdp_rec~.c')
-rw-r--r--modules/pdp_rec~.c705
1 files changed, 705 insertions, 0 deletions
diff --git a/modules/pdp_rec~.c b/modules/pdp_rec~.c
new file mode 100644
index 0000000..7f879d0
--- /dev/null
+++ b/modules/pdp_rec~.c
@@ -0,0 +1,705 @@
+/*
+ * PiDiP module.
+ * Copyright (c) by Yves Degoyon <ydegoyon@free.fr>
+ *
+ * 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 video recording object
+ * It records its input in quicktime format
+ */
+
+
+#include "pdp.h"
+#include <math.h>
+#include <time.h>
+#include <sys/time.h>
+#include <quicktime/quicktime.h>
+#include <quicktime/colormodels.h>
+
+#define DEFAULT_FRAME_RATE 25
+#define DEFAULT_CHANNELS 2
+#define DEFAULT_BITS 8
+#define DEFAULT_QUALITY 75 // from 1 to 100
+#define MAX_COMP_LENGTH 8
+#define MAX_AUDIO_PACKET_SIZE (128 * 1024)
+
+static char *pdp_rec_version = "pdp_rec~: version 0.1, a video/audio recording object, written by ydegoyon@free.fr";
+
+typedef struct pdp_rec_struct
+{
+ t_object x_obj;
+ t_float x_f;
+
+ t_outlet *x_outlet0;
+ t_int x_packet0;
+ t_int x_packet1;
+ t_int x_dropped;
+ t_int x_queue_id;
+
+ t_int x_vwidth;
+ t_int x_vheight;
+ t_int x_vsize;
+
+ quicktime_t *x_qtfile;
+ unsigned char **x_yuvpointers;
+ unsigned char *x_yuvbuffer;
+ t_int x_framerate;
+ t_int x_forced_framerate;
+ t_int x_jpeg_quality;
+ t_int x_newfile;
+ char *x_compressor;
+ t_int x_recflag;
+ t_int x_frameswritten;
+ struct timeval x_tstart;
+ struct timeval x_tstop;
+ struct timeval x_tlastrec;
+
+ /* audio structures */
+ int16_t **x_audio_buf; /* buffer for incoming audio */
+ t_int x_audioin_position; // writing position for incoming audio
+ char *x_acompressor; // audio compressor
+ t_int x_channels; // audio channels
+ t_int x_samplerate; // audio sample rate
+ t_int x_bits; // audio bits
+
+} t_pdp_rec;
+
+static void pdp_rec_free_ressources(t_pdp_rec *x)
+{
+ if ( x->x_yuvpointers ) freebytes ( x->x_yuvpointers, 3*sizeof( unsigned char** ) );
+ if ( x->x_yuvbuffer ) freebytes ( x->x_yuvbuffer, x->x_vsize + (x->x_vsize>>1) );
+
+}
+
+static void pdp_rec_allocate(t_pdp_rec *x)
+{
+ int i;
+
+ x->x_yuvpointers = (unsigned char**) getbytes ( 3*sizeof(unsigned char**) );
+ x->x_yuvbuffer = (unsigned char*) getbytes ( x->x_vsize + (x->x_vsize>>1) );
+ x->x_yuvpointers[0] = &x->x_yuvbuffer[0];
+ x->x_yuvpointers[2] = &x->x_yuvbuffer[x->x_vsize];
+ x->x_yuvpointers[1] = &x->x_yuvbuffer[x->x_vsize + (x->x_vsize>>2)];
+}
+
+ /* set video track whenever width or height is changed */
+static void pdp_rec_set_video(t_pdp_rec *x)
+{
+ t_int ret;
+
+ if ( !x->x_qtfile ) {
+ post( "pdp_rec~ : no video recording file is opened !!");
+ return;
+ }
+
+ if( ( ret = quicktime_set_video(x->x_qtfile, 1, x->x_vwidth, x->x_vheight, x->x_framerate, x->x_compressor) ) != 0) {
+ post( "pdp_rec~ : error setting video track ret=%d", ret );
+ } else {
+ post( "pdp_rec~ : video track set" );
+ }
+
+ quicktime_set_copyright(x->x_qtfile, "");
+ quicktime_set_name(x->x_qtfile, "Pdp output");
+ quicktime_set_info(x->x_qtfile, "File created with PDP/PiDiP");
+
+}
+
+ /* set framerate */
+static void pdp_rec_set_framerate(t_pdp_rec *x)
+{
+ t_int ret;
+
+ if ( !x->x_qtfile ) {
+ post( "pdp_rec~ : no video recording file is opened !!");
+ return;
+ }
+
+ quicktime_set_framerate(x->x_qtfile, (float)x->x_framerate );
+ post( "pdp_rec~ : framerate set to : %d", x->x_framerate );
+
+}
+
+ /* set audio track */
+static void pdp_rec_set_audio(t_pdp_rec *x)
+{
+ t_int ret;
+
+ if ( !x->x_qtfile ) {
+ post( "pdp_rec~ : no video recording file is opened !!");
+ return;
+ }
+
+ if( ( ret = quicktime_set_audio(x->x_qtfile, x->x_channels, x->x_samplerate, x->x_bits, x->x_acompressor ) ) == 0)
+ {
+ post( "pdp_rec~ : error setting audio track ret=%d", ret );
+ post( "pdp_rec~ : params : samplerate=%d : compressor=%s : channels=%d : bits=%d",
+ x->x_samplerate, x->x_acompressor, x->x_channels, x->x_bits );
+ } else {
+ post( "pdp_rec~ : %d audio track(s) allocated.", ret );
+ }
+
+}
+
+ /* set color model : it's hard coded : only one model supported */
+static void pdp_rec_set_cmodel(t_pdp_rec *x)
+{
+ t_int ret;
+
+ if ( !x->x_qtfile ) {
+ post( "pdp_rec~ : no video recording file is opened !!");
+ return;
+ }
+
+ quicktime_set_cmodel(x->x_qtfile, BC_YUV420P );
+ post( "pdp_rec~ : color model set" );
+
+}
+
+static void pdp_rec_set_jpeg(t_pdp_rec *x)
+{
+ if ( !x->x_qtfile )
+ {
+ post( "pdp_rec~ : set jpeg : no video recording file is opened !!");
+ return;
+ }
+
+ if ( strcmp( x->x_compressor, QUICKTIME_JPEG ) )
+ {
+ post( "pdp_rec~ : set jpeg : the codec is not jpeg right now !!");
+ return;
+ }
+ quicktime_set_jpeg( x->x_qtfile, x->x_jpeg_quality, 1 );
+ post( "pdp_rec~ : jpeg quality factor set : %d", x->x_jpeg_quality );
+}
+
+static void pdp_rec_frame_rate(t_pdp_rec *x, t_floatarg frate )
+{
+ if ( frate >= 1 )
+ {
+ x->x_framerate = (int) frate;
+ x->x_forced_framerate = 1;
+ post( "pdp_rec~ : frame rate set to %d : open a new file to activate it", x->x_framerate );
+ }
+}
+
+static void pdp_rec_jpeg(t_pdp_rec *x, t_floatarg fjpeg )
+{
+ if ( ( fjpeg >= 1 ) && ( fjpeg <= 100 ))
+ {
+ x->x_jpeg_quality = (int) fjpeg;
+ post( "pdp_rec~ : jpeg quality set : open a new file to activate it" );
+ }
+}
+
+static void pdp_rec_compressor(t_pdp_rec *x, t_symbol *scompressor )
+{
+ char scomp[ MAX_COMP_LENGTH ];
+
+ // check compressor as defined in quicktime.h
+ if (
+ strcmp( scompressor->s_name, "divx")
+ && strcmp( scompressor->s_name, "dv")
+ && strcmp( scompressor->s_name, "raw")
+ && strcmp( scompressor->s_name, "jpeg")
+ // && strcmp( scompressor->s_name, "png") // crashes with libquicktime 0.9.1
+ // && strcmp( scompressor->s_name, "mjpa") // no output with libquicktime 0.9.1
+ && strcmp( scompressor->s_name, "yuv2")
+ // && strcmp( scompressor->s_name, "yuv4") // crashes with libquicktime 0.9.1
+ )
+ {
+ post( "pdp_rec~ : unsupported codec : %s", scompressor->s_name );
+ return;
+ }
+
+ // map message names to libquicktime names
+ if ( !strcmp( scompressor->s_name, "divx") )
+ {
+ strcpy( scomp, QUICKTIME_DIVX );
+ }
+ if ( !strcmp( scompressor->s_name, "dv") )
+ {
+ strcpy( scomp, QUICKTIME_DV );
+ }
+ if ( !strcmp( scompressor->s_name, "raw") )
+ {
+ strcpy( scomp, QUICKTIME_RAW );
+ }
+ if ( !strcmp( scompressor->s_name, "jpeg") )
+ {
+ strcpy( scomp, QUICKTIME_JPEG );
+ }
+ if ( !strcmp( scompressor->s_name, "png") )
+ {
+ strcpy( scomp, QUICKTIME_PNG );
+ }
+ if ( !strcmp( scompressor->s_name, "mjpa") )
+ {
+ strcpy( scomp, QUICKTIME_MJPA );
+ }
+ if ( !strcmp( scompressor->s_name, "yuv2") )
+ {
+ strcpy( scomp, QUICKTIME_YUV2 );
+ }
+ if ( !strcmp( scompressor->s_name, "yuv4") )
+ {
+ strcpy( scomp, QUICKTIME_YUV4 );
+ }
+
+ if ( x->x_compressor )
+ {
+ freebytes( x->x_compressor, strlen( x->x_compressor )+1 );
+ }
+ x->x_compressor = (char *) getbytes( strlen( scomp ) + 1 );
+ strcpy( x->x_compressor, scomp );
+ post( "pdp_rec~ : compressor set to %s : open a new file to activate it", scomp );
+}
+
+ /* set audio compressor */
+static void pdp_rec_acompressor(t_pdp_rec *x, t_symbol *scompressor )
+{
+ char scomp[ MAX_COMP_LENGTH ];
+
+ // check compressor as defined in quicktime.h
+ if (
+ strcmp( scompressor->s_name, "twos")
+ // && strcmp( scompressor->s_name, "ima4") // produces a lot of errors ( libquicktime 0.9.1 )
+ && strcmp( scompressor->s_name, "raw")
+ // && strcmp( scompressor->s_name, "ulaw") // produces a lot of errors ( libquicktime 0.9.1 )
+ // && strcmp( scompressor->s_name, "ogg") // produces a lot of errors ( libquicktime 0.9.1 )
+ )
+ {
+ post( "pdp_rec~ : unsupported codec : %s", scompressor->s_name );
+ return;
+ }
+
+ // map message names to libquicktime names
+ if ( !strcmp( scompressor->s_name, "raw") )
+ {
+ strcpy( scomp, QUICKTIME_RAW );
+ }
+ if ( !strcmp( scompressor->s_name, "ima4") )
+ {
+ strcpy( scomp, QUICKTIME_IMA4 );
+ }
+ if ( !strcmp( scompressor->s_name, "twos") )
+ {
+ strcpy( scomp, QUICKTIME_TWOS );
+ }
+ if ( !strcmp( scompressor->s_name, "ulaw") )
+ {
+ strcpy( scomp, QUICKTIME_ULAW );
+ }
+ if ( !strcmp( scompressor->s_name, "ogg") )
+ {
+ strcpy( scomp, QUICKTIME_VORBIS );
+ }
+
+ if ( x->x_compressor )
+ {
+ freebytes( x->x_compressor, strlen( x->x_compressor )+1 );
+ }
+ x->x_compressor = (char *) getbytes( strlen( scomp ) + 1 );
+ strcpy( x->x_compressor, scomp );
+ post( "pdp_rec~ : audio compressor set to %s : open a new file to activate it", scomp );
+}
+
+ /* close a video file */
+static void pdp_rec_close(t_pdp_rec *x)
+{
+ int ret;
+
+ if ( x->x_qtfile ) {
+ if( ( ret = quicktime_close(x->x_qtfile) ) != 0 ) {
+ post( "pdp_rec~ : error closing file ret=%d", ret );
+ } else {
+ post( "pdp_rec~ : closed video file" );
+ x->x_qtfile = NULL;
+ }
+ }
+}
+
+ /* open a new video file */
+static void pdp_rec_open(t_pdp_rec *x, t_symbol *sfile)
+{
+ t_int ret=0;
+
+ // close previous video file if existing
+ pdp_rec_close(x);
+
+ if ( x->x_recflag ) {
+ x->x_recflag = 0;
+ }
+
+ if ( ( x->x_qtfile = quicktime_open(sfile->s_name, 0, 1) ) == NULL )
+ {
+ error( "pdp_rec~ : cannot open >%s<", sfile->s_name);
+ error( "pdp_rec~ : ret=%d", ret );
+ x->x_qtfile = NULL;
+ return;
+ } else {
+ x->x_frameswritten = 0;
+ post( "pdp_rec~ : opened >%s<", sfile->s_name);
+ x->x_newfile = 1;
+ }
+
+}
+
+ /* start recording */
+static void pdp_rec_start(t_pdp_rec *x)
+{
+ if ( !x->x_qtfile ) {
+ post("pdp_rec~ : start received but no file has been opened ... ignored.");
+ return;
+ }
+
+ if ( x->x_recflag == 1 ) {
+ post("pdp_rec~ : start received but recording is started ... ignored.");
+ return;
+ }
+
+ if ( gettimeofday(&x->x_tstart, NULL) == -1)
+ {
+ post("pdp_rec~ : could not set start time" );
+ }
+
+ x->x_recflag = 1;
+ post("pdp_rec~ : start recording");
+}
+
+ /* stop recording */
+static void pdp_rec_stop(t_pdp_rec *x)
+{
+ if ( !x->x_qtfile ) {
+ post("pdp_rec~ : stop received but no file has been opened ... ignored.");
+ return;
+ }
+
+ if ( x->x_recflag == 0 ) {
+ post("pdp_rec~ : stop received but recording is stopped ... ignored.");
+ return;
+ }
+
+ if ( gettimeofday(&x->x_tstop, NULL) == -1)
+ {
+ post("pdp_rec~ : could set stop time" );
+ }
+
+ // calculate frame rate if it hasn't been set
+ if ( !x->x_forced_framerate )
+ {
+ if ( ( x->x_tstop.tv_sec - x->x_tstart.tv_sec ) > 0 )
+ {
+ x->x_framerate = x->x_frameswritten / ( x->x_tstop.tv_sec - x->x_tstart.tv_sec );
+ }
+ else
+ {
+ x->x_framerate = DEFAULT_FRAME_RATE;
+ }
+ }
+
+ pdp_rec_set_framerate(x);
+
+ x->x_recflag = 0;
+ pdp_rec_close(x);
+
+ post("pdp_rec~ : stop recording");
+}
+
+ /* store audio data in PCM format in a buffer for now */
+static t_int *pdp_rec_perform(t_int *w)
+{
+ t_float *in1 = (t_float *)(w[1]); // left audio inlet
+ t_float *in2 = (t_float *)(w[2]); // right audio inlet
+ t_pdp_rec *x = (t_pdp_rec *)(w[3]);
+ int n = (int)(w[4]); // number of samples
+ t_float fsample;
+ t_int isample, i;
+
+ if ( x->x_recflag )
+ {
+
+ // just fills the buffer
+ while (n--)
+ {
+ fsample=*(in1++);
+ if (fsample > 1.0) { fsample = 1.0; }
+ if (fsample < -1.0) { fsample = -1.0; }
+ isample=(short) (32767.0 * fsample);
+ x->x_audio_buf[0][x->x_audioin_position]=isample;
+ fsample=*(in2++);
+ if (fsample > 1.0) { fsample = 1.0; }
+ if (fsample < -1.0) { fsample = -1.0; }
+ isample=(short) (32767.0 * fsample);
+ x->x_audio_buf[1][x->x_audioin_position]=isample;
+ x->x_audioin_position=(x->x_audioin_position+1)%(2*MAX_AUDIO_PACKET_SIZE);
+ if ( x->x_audioin_position == 2*MAX_AUDIO_PACKET_SIZE-1 )
+ {
+ post( "pdp_rec~ : reaching end of audio buffer" );
+ }
+ }
+
+ }
+
+ return (w+5);
+}
+
+static void pdp_rec_dsp(t_pdp_rec *x, t_signal **sp)
+{
+ dsp_add(pdp_rec_perform, 4, sp[0]->s_vec, sp[1]->s_vec, x, sp[0]->s_n);
+}
+
+static void pdp_rec_process_yv12(t_pdp_rec *x)
+{
+ t_pdp *header = pdp_packet_header(x->x_packet0);
+ short int *data = (short int *)pdp_packet_data(x->x_packet0);
+ t_int i, ret;
+ t_int px, py;
+ unsigned short *poy, *pou, *pov;
+ struct timeval trec;
+ t_int nbaudiosamples, nbusecs, nbrecorded;
+ t_float fframerate=0.0;
+
+ x->x_vwidth = header->info.image.width;
+ x->x_vheight = header->info.image.height;
+ x->x_vsize = x->x_vwidth*x->x_vheight;
+
+ /* setting video track */
+ if ( x->x_qtfile && x->x_recflag )
+ {
+ if ( ( (int)(header->info.image.width) != x->x_vwidth ) ||
+ ( (int)(header->info.image.height) != x->x_vheight ) ||
+ ( x->x_newfile ) )
+ {
+ pdp_rec_free_ressources(x);
+ x->x_newfile = 0;
+ if ( x->x_qtfile ) {
+ pdp_rec_set_video(x);
+ pdp_rec_set_audio(x);
+ pdp_rec_set_cmodel(x);
+ if ( !strcmp( x->x_compressor, QUICKTIME_JPEG ) )
+ {
+ pdp_rec_set_jpeg(x);
+ }
+ }
+ pdp_rec_allocate(x);
+ }
+
+ if ( x->x_frameswritten == 0 )
+ {
+ if ( gettimeofday(&x->x_tlastrec, NULL) == -1)
+ {
+ post("pdp_rec~ : could set stop time" );
+ }
+ }
+
+ for (i=0; i<x->x_vsize; i++)
+ {
+ x->x_yuvbuffer[i] = data[i]>>7;
+ }
+ for (i=x->x_vsize; i<(x->x_vsize+(x->x_vsize>>1)); i++)
+ {
+ x->x_yuvbuffer[i] = ((data[i]>>8)+128);
+ }
+
+ if ( ( ret = quicktime_encode_video(x->x_qtfile, x->x_yuvpointers, 0) ) != 0 )
+ {
+ post( "pdp_rec~ : error writing frame : ret=%d", ret );
+ }
+ else
+ {
+ x->x_frameswritten++;
+ }
+
+ // calculate the number of audio samples to output
+ if ( gettimeofday(&trec, NULL) == -1)
+ {
+ post("pdp_rec~ : could set stop time" );
+ }
+ // calculate time diff in micro seconds
+ nbusecs = ( trec.tv_usec - x->x_tlastrec.tv_usec ) + ( trec.tv_sec - x->x_tlastrec.tv_sec )*1000000;
+ nbaudiosamples = (sys_getsr()*1000000)/nbusecs;
+ memcpy( &x->x_tlastrec, &trec, sizeof( struct timeval) );
+
+ if ( x->x_audioin_position > nbaudiosamples )
+ {
+ nbrecorded = nbaudiosamples;
+ }
+ else
+ {
+ nbrecorded = x->x_audioin_position;
+ }
+
+ if ( ( ret = quicktime_encode_audio(x->x_qtfile, x->x_audio_buf, NULL, nbrecorded) ) != 0 )
+ {
+ post( "pdp_rec~ : error writing audio data : ret=%d", ret );
+ }
+ else
+ {
+ memcpy( &x->x_audio_buf[0][0], &x->x_audio_buf[0][nbrecorded], x->x_audioin_position-nbrecorded );
+ memcpy( &x->x_audio_buf[1][0], &x->x_audio_buf[1][nbrecorded], x->x_audioin_position-nbrecorded );
+ x->x_audioin_position -= nbrecorded;
+ // post ( "pdp_rec~ : recorded %d samples.", nbrecorded );
+ }
+ }
+
+ return;
+}
+
+static void pdp_rec_killpacket(t_pdp_rec *x)
+{
+ /* release the packet */
+ pdp_packet_mark_unused(x->x_packet0);
+ x->x_packet0 = -1;
+}
+
+static void pdp_rec_process(t_pdp_rec *x)
+{
+ int encoding;
+ t_pdp *header = 0;
+
+ /* check if image data packets are compatible */
+ if ( (header = pdp_packet_header(x->x_packet0))
+ && (PDP_IMAGE == header->type)){
+
+ /* pdp_rec_process inputs and write into active inlet */
+ switch(pdp_packet_header(x->x_packet0)->info.image.encoding)
+ {
+
+ case PDP_IMAGE_YV12:
+ if ( x->x_qtfile && x->x_recflag )
+ {
+ outlet_float( x->x_obj.ob_outlet, x->x_frameswritten );
+ }
+ pdp_queue_add(x, pdp_rec_process_yv12, pdp_rec_killpacket, &x->x_queue_id);
+ break;
+
+ case PDP_IMAGE_GREY:
+ // should write something to handle these one day
+ // but i don't use this mode
+ break;
+
+ default:
+ /* don't know the type, so dont pdp_rec_process */
+ break;
+
+ }
+ }
+
+}
+
+static void pdp_rec_input_0(t_pdp_rec *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("image/YCrCb/*") );
+
+ if ((s == gensym("process")) && (-1 != x->x_packet0) && (!x->x_dropped))
+ {
+ /* add the process method and callback to the process queue */
+ pdp_rec_process(x);
+ }
+
+}
+
+static void pdp_rec_free(t_pdp_rec *x)
+{
+ int i;
+
+ pdp_queue_finish(x->x_queue_id);
+ pdp_packet_mark_unused(x->x_packet0);
+ // close video file if existing
+ pdp_rec_close(x);
+ for ( i=0; i<x->x_channels; i++)
+ {
+ if ( x->x_audio_buf[i] ) freebytes( x->x_audio_buf[i], MAX_AUDIO_PACKET_SIZE*sizeof(int16_t) );
+ }
+ if ( x->x_audio_buf ) freebytes( x->x_audio_buf, x->x_channels*sizeof(int16_t*) );
+
+}
+
+t_class *pdp_rec_class;
+
+void *pdp_rec_new(void)
+{
+ t_int i;
+
+ t_pdp_rec *x = (t_pdp_rec *)pd_new(pdp_rec_class);
+ inlet_new (&x->x_obj, &x->x_obj.ob_pd, gensym ("signal"), gensym ("signal"));
+ outlet_new (&x->x_obj, &s_float);
+
+ x->x_packet0 = -1;
+ x->x_packet1 = -1;
+ x->x_queue_id = -1;
+
+ x->x_qtfile = NULL;
+ x->x_framerate = DEFAULT_FRAME_RATE;
+ x->x_forced_framerate = 0;
+ x->x_compressor = (char*) getbytes( strlen(QUICKTIME_JPEG)+1 );
+ strcpy( x->x_compressor, QUICKTIME_JPEG );
+
+ /* audio defaults */
+ x->x_acompressor = (char*) getbytes( strlen(QUICKTIME_TWOS)+1 );
+ strcpy( x->x_acompressor, QUICKTIME_TWOS );
+ x->x_samplerate = sys_getsr();
+ x->x_channels = DEFAULT_CHANNELS;
+ x->x_bits = DEFAULT_BITS;
+
+ x->x_audio_buf = (int16_t**) getbytes( x->x_channels*sizeof(int16_t*) );
+ for ( i=0; i<x->x_channels; i++)
+ {
+ x->x_audio_buf[i] = (int16_t*) getbytes( MAX_AUDIO_PACKET_SIZE*sizeof(int16_t) );
+ }
+
+ x->x_newfile = 0;
+ x->x_yuvbuffer = NULL;
+ x->x_yuvpointers = NULL;
+ x->x_jpeg_quality = DEFAULT_QUALITY;
+
+ return (void *)x;
+}
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+void pdp_rec_tilde_setup(void)
+{
+ post( pdp_rec_version );
+ pdp_rec_class = class_new(gensym("pdp_rec~"), (t_newmethod)pdp_rec_new,
+ (t_method)pdp_rec_free, sizeof(t_pdp_rec), 0, A_NULL);
+
+ CLASS_MAINSIGNALIN(pdp_rec_class, t_pdp_rec, x_f );
+ class_addmethod(pdp_rec_class, (t_method)pdp_rec_dsp, gensym("dsp"), 0);
+ class_addmethod(pdp_rec_class, (t_method)pdp_rec_input_0, gensym("pdp"), A_SYMBOL, A_DEFFLOAT, A_NULL);
+ class_addmethod(pdp_rec_class, (t_method)pdp_rec_open, gensym("open"), A_SYMBOL, A_NULL);
+ class_addmethod(pdp_rec_class, (t_method)pdp_rec_close, gensym("close"), A_NULL);
+ class_addmethod(pdp_rec_class, (t_method)pdp_rec_frame_rate, gensym("framerate"), A_DEFFLOAT, A_NULL);
+ class_addmethod(pdp_rec_class, (t_method)pdp_rec_compressor, gensym("compressor"), A_SYMBOL, A_NULL);
+ class_addmethod(pdp_rec_class, (t_method)pdp_rec_acompressor, gensym("acompressor"), A_SYMBOL, A_NULL);
+ class_addmethod(pdp_rec_class, (t_method)pdp_rec_jpeg, gensym("jpeg"), A_DEFFLOAT, A_NULL);
+ class_addmethod(pdp_rec_class, (t_method)pdp_rec_start, gensym("start"), A_NULL);
+ class_addmethod(pdp_rec_class, (t_method)pdp_rec_stop, gensym("stop"), A_NULL);
+
+}
+
+#ifdef __cplusplus
+}
+#endif