hornetseye-qt4 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/rubytools.hh ADDED
@@ -0,0 +1,33 @@
1
+ /* HornetsEye - Computer Vision with Ruby
2
+ Copyright (C) 2006, 2007 Jan Wedekind
3
+
4
+ This program is free software: you can redistribute it and/or modify
5
+ it under the terms of the GNU General Public License as published by
6
+ the Free Software Foundation, either version 3 of the License, or
7
+ (at your option) any later version.
8
+
9
+ This program is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU General Public License for more details.
13
+
14
+ You should have received a copy of the GNU General Public License
15
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
16
+ #ifndef HORNETSEYE_RUBYTOOLS_HH
17
+ #define HORNETSEYE_RUBYTOOLS_HH
18
+
19
+ #include <complex>
20
+ #include "rubyinc.hh"
21
+
22
+ void checkType( VALUE rbValue, VALUE rbClass );
23
+
24
+ void checkStruct( VALUE rbValue, VALUE rbClass );
25
+
26
+ #define dataGetStruct(obj,klass,type,sval) { \
27
+ checkStruct( obj, klass ); \
28
+ Data_Get_Struct( obj, type, sval ); \
29
+ }
30
+
31
+ #include "rubytools.tcc"
32
+
33
+ #endif
data/ext/rubytools.tcc ADDED
@@ -0,0 +1,32 @@
1
+ /* HornetsEye - Computer Vision with Ruby
2
+ Copyright (C) 2006, 2007 Jan Wedekind
3
+
4
+ This program is free software: you can redistribute it and/or modify
5
+ it under the terms of the GNU General Public License as published by
6
+ the Free Software Foundation, either version 3 of the License, or
7
+ (at your option) any later version.
8
+
9
+ This program is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU General Public License for more details.
13
+
14
+ You should have received a copy of the GNU General Public License
15
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
16
+ #include <cassert>
17
+ #include "error.hh"
18
+
19
+ inline void checkType( VALUE rbValue, VALUE rbClass )
20
+ {
21
+ ERRORMACRO( rb_funcall( rbValue, rb_intern( "kind_of?" ), 1, rbClass ) ==
22
+ Qtrue, Error, ,
23
+ "Argument must be of class \"" << rb_class2name( rbClass )
24
+ << "\"." );
25
+ }
26
+
27
+ inline void checkStruct( VALUE rbValue, VALUE rbClass )
28
+ {
29
+ Check_Type( rbValue, T_DATA );
30
+ checkType( rbValue, rbClass );
31
+ }
32
+
data/ext/xvwidget.cc ADDED
@@ -0,0 +1,501 @@
1
+ /* HornetsEye - Computer Vision with Ruby
2
+ Copyright (C) 2006, 2007, 2008, 2009 Jan Wedekind
3
+
4
+ This program is free software: you can redistribute it and/or modify
5
+ it under the terms of the GNU General Public License as published by
6
+ the Free Software Foundation, either version 3 of the License, or
7
+ (at your option) any later version.
8
+
9
+ This program is distributed in the hope that it will be useful,
10
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ GNU General Public License for more details.
13
+
14
+ You should have received a copy of the GNU General Public License
15
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
16
+ #ifndef NDEBUG
17
+ #include <iostream>
18
+ #include <iomanip>
19
+ #endif
20
+
21
+ using namespace std;
22
+
23
+ #include <QtCore/QCoreApplication>
24
+ #include <QtGui/QX11Info>
25
+ #include "rubytools.hh"
26
+ #include "xvwidget.hh"
27
+
28
+ // also see xvideoimagepainter.cc
29
+
30
+ std::map< VALUE, XvManagerPtr > xvManager;
31
+
32
+ VALUE XvManager::cRubyClass = Qnil;
33
+ VALUE XvManager::rbHornetseye = Qnil;
34
+
35
+ std::set< XvPortID > XvManager::grabbedPorts;
36
+
37
+ XvManager::XvManager( QWidget *widget ):
38
+ m_widget(widget), m_port(0), m_requireColourKey(false), m_colourKey(0),
39
+ m_xvImage(NULL)
40
+ {
41
+ m_widget->setAttribute( Qt::WA_NoSystemBackground );
42
+ m_widget->setAttribute( Qt::WA_OpaquePaintEvent );
43
+ m_widget->setAttribute( Qt::WA_PaintOnScreen );
44
+ m_widget->setAutoFillBackground( false );
45
+ }
46
+
47
+ void XvManager::paint(void) throw (Error)
48
+ {
49
+ Display *display = m_widget->x11Info().display();
50
+ ERRORMACRO( display != NULL, Error, ,
51
+ "Connection to X server does not exist" );
52
+ int id = m_widget->winId();
53
+ XGCValues xgcv;
54
+ GC gc = XCreateGC( display, id, 0L, &xgcv );
55
+ if ( m_xvImage != NULL ) {
56
+ if ( m_requireColourKey ) {
57
+ XSetForeground( display, gc, m_colourKey );
58
+ XFillRectangle( display, id, gc, 0, 0,
59
+ m_widget->width(), m_widget->height() );
60
+ };
61
+ } else {
62
+ XSetForeground( display, gc, 0 );
63
+ XFillRectangle( display, id, gc, 0, 0,
64
+ m_widget->width(), m_widget->height() );
65
+ };
66
+ XFreeGC( display, gc );
67
+ }
68
+
69
+ void XvManager::grabPort(void) throw (Error)
70
+ {
71
+ if ( m_port == 0 ) {
72
+ // check whether m_port is zero !!!
73
+ Display *display = m_widget->x11Info().display();
74
+ ERRORMACRO( display != NULL, Error, ,
75
+ "Connection to X server does not exist" );
76
+ unsigned int ver, rel, req, ev, err;
77
+ ERRORMACRO( XvQueryExtension( display, &ver, &rel, &req, &ev,
78
+ &err ) == Success, Error, ,
79
+ "Failure requesting X video extension" );
80
+ unsigned int numAdaptors;
81
+ XvAdaptorInfo *adaptorInfo = NULL;
82
+ ERRORMACRO( XvQueryAdaptors( display,
83
+ DefaultRootWindow( display ),// correct? !!!
84
+ &numAdaptors, &adaptorInfo ) == Success,
85
+ Error, , "Error requesting information about X video "
86
+ "adaptors." );
87
+ for ( int i=0; i<(signed)numAdaptors; i++ ) {
88
+ if ( ( adaptorInfo[i].type & ( XvInputMask | XvImageMask ) ) ==
89
+ ( XvInputMask | XvImageMask ) ) {
90
+ for ( int p=adaptorInfo[i].base_id;
91
+ p<(signed)(adaptorInfo[i].base_id+adaptorInfo[i].num_ports);
92
+ p++ )
93
+ // API does not seem to protect against grabbing a port
94
+ // twice (from within the same process).
95
+ if ( grabbedPorts.find( p ) == grabbedPorts.end() ) {
96
+ if ( XvGrabPort( display, p, CurrentTime ) == Success ) {
97
+ #ifndef NDEBUG
98
+ cerr << "Grabbed port " << p << endl;
99
+ #endif
100
+ grabbedPorts.insert( p );
101
+ m_port = p;
102
+ break;
103
+ };
104
+ };
105
+ if ( m_port != 0 )
106
+ break;
107
+ };
108
+ };
109
+ XvFreeAdaptorInfo( adaptorInfo );
110
+ ERRORMACRO( m_port != 0, Error, ,
111
+ "Could not grab a free port for X video output." );
112
+ try {
113
+ Atom xvColourKey = findAtom( display, "XV_COLORKEY" );
114
+ if ( xvColourKey != None ) {
115
+ #ifndef NDEBUG
116
+ cerr << "Require drawing of colourkey." << endl;
117
+ #endif
118
+ m_requireColourKey = true;
119
+ ERRORMACRO( XvGetPortAttribute( display, m_port, xvColourKey,
120
+ &m_colourKey ) == Success,
121
+ Error, , "Error reading value of colour-key." );
122
+ #ifndef NDEBUG
123
+ cerr << "Colour-key is 0x" << setw( 6 ) << setbase( 16 )
124
+ << m_colourKey << setbase( 10 ) << setw( 0 ) << endl;
125
+ #endif
126
+ Atom xvAutoPaint = findAtom( display, "XV_AUTOPAINT_COLORKEY" );
127
+ if ( xvAutoPaint != None ) {
128
+ #ifndef NDEBUG
129
+ cerr << "Disabling autopainting." << endl;
130
+ #endif
131
+ XvSetPortAttribute( display, m_port, xvAutoPaint, 0 );
132
+ } else {
133
+ #ifndef NDEBUG
134
+ cerr << "Graphic card does not provide autopainting." << endl;
135
+ #endif
136
+ };
137
+ } else {
138
+ m_requireColourKey = false;
139
+ #ifndef NDEBUG
140
+ cerr << "No drawing of colourkey required." << endl;
141
+ #endif
142
+ };
143
+
144
+ } catch ( Error &e ) {
145
+
146
+ XvUngrabPort( display, m_port, CurrentTime );
147
+ grabbedPorts.erase( m_port );
148
+ throw e;
149
+
150
+ };
151
+ };
152
+ }
153
+
154
+ void XvManager::releasePort(void)
155
+ {
156
+ clear();
157
+ if ( m_port != 0 ) {
158
+ Display *display = m_widget->x11Info().display();
159
+ if ( display != NULL )
160
+ XvUngrabPort( display, m_port, CurrentTime );
161
+ grabbedPorts.erase( m_port );
162
+ };
163
+ }
164
+
165
+ void XvManager::clear(void)
166
+ {
167
+ if ( m_xvImage != NULL ) {
168
+ XFree( m_xvImage );
169
+ m_xvImage = NULL;
170
+ m_widget->update();
171
+ };
172
+ }
173
+
174
+ void XvManager::write( FramePtr frame ) throw (Error)
175
+ {
176
+ Display *display = m_widget->x11Info().display();
177
+ ERRORMACRO( display != NULL, Error, ,
178
+ "Connection to X server does not exist" );
179
+ ERRORMACRO( m_port != 0, Error, ,
180
+ "Need to grab XVideo port before image can be displayed." );
181
+ if ( frame ) {
182
+ #ifndef NDEBUG
183
+ cerr << "XVideo-output for \"" << frame->typecode() << "\"." << endl;
184
+ #endif
185
+ int uid = selectFormat( display, typecodeToUID( frame->typecode() ) );
186
+ ERRORMACRO( uid != 0, Error, , "XVideo-extension does not "
187
+ "support YV12, I420, or RGB24" );
188
+ string typecode = uidToTypecode( uid );
189
+ if ( frame->typecode() != typecode ) {
190
+ VALUE
191
+ rbTypecode = rb_funcall( rbHornetseye, rb_intern( "const_get" ), 1,
192
+ rb_str_new( typecode.c_str(),
193
+ typecode.length() ) ),
194
+ rbFrame = rb_funcall( frame->rubyObject(), rb_intern( "to_type" ), 1,
195
+ rbTypecode );
196
+ frame = FramePtr( new Frame( rbFrame ) );
197
+ };
198
+ if ( m_xvImage != NULL ) {
199
+ if ( m_xvImage->id != uid ||
200
+ m_xvImage->width != frame->width() ||
201
+ m_xvImage->height != frame->height() ) {
202
+ XFree( m_xvImage );
203
+ m_xvImage = NULL;
204
+ };
205
+ };
206
+ if ( m_xvImage == NULL ) {
207
+ m_xvImage =
208
+ XvCreateImage( display, m_port, uid,
209
+ (char *)frame->data(),
210
+ frame->width(), frame->height() );
211
+ m_widget->update();
212
+ #ifndef NDEBUG
213
+ cerr << "Created " << m_xvImage->width << 'x'
214
+ << m_xvImage->height << ' ' << frame->typecode()
215
+ << "-image for X video." << endl;
216
+ cerr << "# planes = " << m_xvImage->num_planes << endl;
217
+ for ( int i=0; i<m_xvImage->num_planes; i++ )
218
+ cerr << "offsets[" << i << "]=" << m_xvImage->offsets[i]
219
+ << endl
220
+ << "pitches[" << i << "]=" << m_xvImage->pitches[i]
221
+ << endl;
222
+ #endif
223
+ } else
224
+ m_xvImage->data = (char *)frame->data();
225
+ if ( frame->typecode() == "YV12" ) {
226
+ // YV12 requires alignment for X video output.
227
+ frame = alignYV12( frame );
228
+ m_xvImage->data = (char *)frame->data();
229
+ };
230
+ XGCValues xgcv;
231
+ int id = m_widget->winId();
232
+ GC gc = XCreateGC( display, id, 0L, &xgcv );
233
+ XvPutImage( display, m_port, id,
234
+ gc, m_xvImage, 0, 0,
235
+ m_xvImage->width, m_xvImage->height, 0, 0,
236
+ m_widget->width(), m_widget->height() );
237
+ XFreeGC( display, gc );
238
+ };
239
+ }
240
+
241
+ int XvManager::selectFormat( Display *display, const int preferredUID )
242
+ throw (Error)
243
+ {
244
+ // Integrated GPL-licensed code from MPlayer (http://www.mplayerhq.hu/).
245
+ assert( m_port != 0 );
246
+ XvImageFormatValues *formats;
247
+ int numFormats;
248
+ formats = XvListImageFormats( display, m_port, &numFormats );
249
+ ERRORMACRO( formats != NULL, Error, ,
250
+ "Error requesting list of image formats." );
251
+ #ifndef NDEBUG
252
+ for ( int i=0; i<numFormats; i++ ) {
253
+ int id = formats[i].id;
254
+ cerr << "format 0x" << setbase( 16 ) << id << setbase( 10 ) << ": '";
255
+ cerr << (char)( id & 0xFF )
256
+ << (char)( ( id >> 8 ) & 0xFF )
257
+ << (char)( ( id >> 16 ) & 0xFF )
258
+ << (char)( ( id >> 24 ) & 0xFF ) << "'";
259
+ if ( formats[i].format == XvPacked )
260
+ cerr << "(packed)" << endl;
261
+ else
262
+ cerr << "(planar)" << endl;
263
+ };
264
+ #endif
265
+ int retVal = 0;
266
+ for ( int i=0; i<numFormats; i++ )
267
+ if ( formats[i].id == preferredUID && preferredUID != 0 ) {
268
+ #ifndef NDEBUG
269
+ cerr << "Found XVideo support for preferred colourspace ";
270
+ cerr << "0x" << setbase( 16 ) << preferredUID << setbase( 10 ) << endl;
271
+ #endif
272
+ retVal = preferredUID;
273
+ break;
274
+ } else if ( retVal == 0 && uidToTypecode( formats[i].id ) != "" ) {
275
+ #ifndef NDEBUG
276
+ cerr << "Selecting \"" << uidToTypecode( formats[i].id )
277
+ << "\" as colourspace for fallback" << endl;
278
+ #endif
279
+ retVal = formats[i].id;
280
+ }
281
+ return retVal;
282
+ }
283
+
284
+ Atom XvManager::findAtom( Display *display, const char *name ) throw (Error)
285
+ {
286
+ // Integrated GPL-licensed code from MPlayer (http://www.mplayerhq.hu/).
287
+ assert( m_port != 0 );
288
+ XvAttribute *attributes;
289
+ int numAttributes;
290
+ attributes = XvQueryPortAttributes( display, m_port,
291
+ &numAttributes );
292
+ ERRORMACRO( attributes != NULL, Error, ,
293
+ "Error requesting attributes of X video port." );
294
+ Atom retVal = None;
295
+ for ( int i=0; i<numAttributes; i++ )
296
+ if ( strcmp( attributes[i].name, name ) == 0 ) {
297
+ retVal = XInternAtom( display, name, False );
298
+ break;
299
+ }
300
+ XFree( attributes );
301
+ return retVal;
302
+ }
303
+
304
+ FramePtr XvManager::alignYV12( FramePtr frame )
305
+ {
306
+ // YV12-images aligned by Xine sometimes do not fit the required
307
+ // output.
308
+ assert( m_xvImage != NULL );
309
+ int
310
+ width = frame->width(),
311
+ height = frame->height(),
312
+ width2 = ( width + 1 ) / 2,
313
+ height2 = ( height + 1 ) / 2,
314
+ widtha = ( width + 7 ) & ~0x7,
315
+ width2a = ( width2 + 7 ) & ~0x7;
316
+ assert( m_xvImage->offsets[0] == 0 );
317
+ FramePtr retVal;
318
+ if ( m_xvImage->offsets[1] != widtha * height ||
319
+ m_xvImage->offsets[2] != widtha * height + width2a * height2 ||
320
+ m_xvImage->pitches[0] != widtha ||
321
+ m_xvImage->pitches[1] != width2a ||
322
+ m_xvImage->pitches[2] != width2a ) {
323
+ #ifndef NDEBUG
324
+ cerr << "YV12-Image needs alignment." << endl;
325
+ #endif
326
+ FramePtr dest( new Frame( "YV12",
327
+ m_xvImage->width, m_xvImage->height ) );
328
+ const char
329
+ *src_y = frame->data();
330
+ const signed char
331
+ *src_v = (const signed char *)src_y + widtha * height,
332
+ *src_u = src_v + width2a * height2;
333
+ unsigned char
334
+ *dest_y = (unsigned char *)dest->data();
335
+ signed char
336
+ *dest_v = (signed char *)dest_y + m_xvImage->offsets[1],
337
+ *dest_u = (signed char *)dest_y + m_xvImage->offsets[2];
338
+ for ( int y=0; y<height; y+=2 ) {
339
+ for ( int x=0; x<width; x+=2 ) {
340
+ dest_y[ 0] = src_y[ 0];
341
+ dest_y[ 1] = src_y[ 1];
342
+ dest_y[m_xvImage->pitches[0] ] = src_y[widtha ];
343
+ dest_y[m_xvImage->pitches[0]+1] = src_y[widtha+1];
344
+ *dest_v = *src_v;
345
+ *dest_u = *src_u;
346
+ src_y += 2;
347
+ src_u++;
348
+ src_v++;
349
+ dest_y += 2;
350
+ dest_u++;
351
+ dest_v++;
352
+ };
353
+ src_y += 2 * widtha - width;
354
+ src_v += width2a - width2;
355
+ src_u += width2a - width2;
356
+ dest_y += 2 * m_xvImage->pitches[0] - width;
357
+ dest_v += m_xvImage->pitches[1] - width2;
358
+ dest_u += m_xvImage->pitches[2] - width2;
359
+ };
360
+ retVal = dest;
361
+ } else
362
+ retVal = frame;
363
+ return retVal;
364
+ }
365
+
366
+ int XvManager::typecodeToUID( string typecode )
367
+ {
368
+ map< string, int > uid;
369
+ uid[ "UBYTERGB" ] = 0x20424752;
370
+ uid[ "YV12" ] = 0x32315659;
371
+ uid[ "I420" ] = 0x30323449;
372
+ map< string, int >::iterator i = uid.find( typecode );
373
+ int retVal = 0;
374
+ if ( i != uid.end() ) retVal = i->second;
375
+ #ifndef NDEBUG
376
+ if ( retVal != 0 )
377
+ cerr << "uid for \"" << typecode << "\" is 0x"
378
+ << setbase( 16 ) << retVal << setbase( 10 ) << endl;
379
+ else
380
+ cerr << "uid for \"" << typecode << "\" was not found";
381
+ #endif
382
+ return retVal;
383
+ }
384
+
385
+ string XvManager::uidToTypecode( int uid )
386
+ {
387
+ map< int, string > typecode;
388
+ typecode[ 0x20424752 ] = "UBYTERGB";
389
+ typecode[ 0x32315659 ] = "YV12";
390
+ typecode[ 0x30323449 ] = "I420";
391
+ map< int, string >::iterator i = typecode.find( uid );
392
+ string retVal = "";
393
+ if ( i != typecode.end() ) retVal = i->second;
394
+ #ifndef NDEBUG
395
+ if ( retVal != "" )
396
+ cerr << "0x" << setbase( 16 ) << uid << setbase( 10 )
397
+ << " designates colourspace \"" << retVal << "\"" << endl;
398
+ else
399
+ cerr << "0x" << setbase( 16 ) << uid << setbase( 10 )
400
+ << " does not designate a known colourspace" << endl;
401
+ #endif
402
+ return retVal;
403
+ }
404
+
405
+ VALUE XvManager::registerRubyClass( VALUE module, VALUE cWidget )
406
+ {
407
+ cRubyClass = rb_define_class_under( module, "XvWidget", cWidget );
408
+ rbHornetseye = module;
409
+ rb_define_singleton_method( cRubyClass, "register",
410
+ RUBY_METHOD_FUNC( XvManager::wrapRegister ),
411
+ 1 );
412
+ rb_define_singleton_method( cRubyClass, "unregister",
413
+ RUBY_METHOD_FUNC( XvManager::wrapUnregister ),
414
+ 1 );
415
+ rb_define_method( cRubyClass, "paintEvent",
416
+ RUBY_METHOD_FUNC( XvManager::wrapPaintEvent ), 1 );
417
+ rb_define_method( cRubyClass, "grabPort",
418
+ RUBY_METHOD_FUNC( XvManager::wrapGrabPort ), 0 );
419
+ rb_define_method( cRubyClass, "releasePort",
420
+ RUBY_METHOD_FUNC( XvManager::wrapReleasePort ), 0 );
421
+ rb_define_method( cRubyClass, "clear",
422
+ RUBY_METHOD_FUNC( XvManager::wrapClear ), 0 );
423
+ rb_define_method( cRubyClass, "write",
424
+ RUBY_METHOD_FUNC( XvManager::wrapWrite ), 1 );
425
+ return cRubyClass;
426
+ }
427
+
428
+ VALUE XvManager::wrapRegister( VALUE rbClass, VALUE rbWidget )
429
+ {
430
+ #ifndef NDEBUG
431
+ cerr << "Registering custom widget ... " << flush;
432
+ #endif
433
+ const char *name = "HORNETSEYE-XVWIDGETFISHING";
434
+ QObject object( QCoreApplication::instance() );
435
+ object.setObjectName( name );
436
+ VALUE rbQObject =
437
+ rb_eval_string( "Qt::CoreApplication.instance.findChild"
438
+ "( Qt::Object, 'HORNETSEYE-XVWIDGETFISHING' )" );
439
+ rb_funcall( rbQObject, rb_intern( "parent=" ), 1, rbWidget );
440
+ xvManager[ rbWidget ] =
441
+ XvManagerPtr( new XvManager( (QWidget *)object.parent() ) );
442
+ #ifndef NDEBUG
443
+ cerr << "done" << endl;
444
+ #endif
445
+ return rbWidget;
446
+ }
447
+
448
+ VALUE XvManager::wrapUnregister( VALUE rbClass, VALUE rbWidget )
449
+ {
450
+ xvManager.erase( rbWidget );
451
+ return rbWidget;
452
+ }
453
+
454
+ VALUE XvManager::wrapGrabPort( VALUE rbSelf )
455
+ {
456
+ try {
457
+ assert( xvManager[ rbSelf ] );
458
+ xvManager[ rbSelf ]->grabPort();
459
+ } catch ( std::exception &e ) {
460
+ rb_raise( rb_eRuntimeError, "%s", e.what() );
461
+ }
462
+ return rbSelf;
463
+ }
464
+
465
+ VALUE XvManager::wrapReleasePort( VALUE rbSelf )
466
+ {
467
+ assert( xvManager[ rbSelf ] );
468
+ xvManager[ rbSelf ]->releasePort();
469
+ return rbSelf;
470
+ }
471
+
472
+ VALUE XvManager::wrapClear( VALUE rbSelf )
473
+ {
474
+ assert( xvManager[ rbSelf ] );
475
+ xvManager[ rbSelf ]->clear();
476
+ return rbSelf;
477
+ }
478
+
479
+ VALUE XvManager::wrapWrite( VALUE rbSelf, VALUE rbFrame )
480
+ {
481
+ try {
482
+ FramePtr frame( new Frame( rbFrame ) );
483
+ assert( xvManager[ rbSelf ] );
484
+ xvManager[ rbSelf ]->write( frame );
485
+ } catch ( std::exception &e ) {
486
+ rb_raise( rb_eRuntimeError, "%s", e.what() );
487
+ }
488
+ return rbFrame;
489
+ }
490
+
491
+ VALUE XvManager::wrapPaintEvent( VALUE rbSelf, VALUE rbPaintEvent )
492
+ {
493
+ try {
494
+ assert( xvManager[ rbSelf ] );
495
+ xvManager[ rbSelf ]->paint();
496
+ } catch ( std::exception &e ) {
497
+ rb_raise( rb_eRuntimeError, "%s", e.what() );
498
+ }
499
+ return rbSelf;
500
+ }
501
+