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/.document +1 -0
- data/COPYING +679 -0
- data/README.md +4 -0
- data/Rakefile +187 -0
- data/ext/error.hh +50 -0
- data/ext/frame.cc +81 -0
- data/ext/frame.hh +43 -0
- data/ext/init.cc +43 -0
- data/ext/rubyinc.hh +54 -0
- data/ext/rubytools.hh +33 -0
- data/ext/rubytools.tcc +32 -0
- data/ext/xvwidget.cc +501 -0
- data/ext/xvwidget.hh +66 -0
- data/lib/hornetseye-qt4/xvwidget.rb +43 -0
- data/lib/hornetseye_qt4_ext.rb +17 -0
- metadata +147 -0
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
|
+
|