1
/* qv4l2: a control panel controlling v4l2 devices.
3
* Copyright (C) 2006 Hans Verkuil <hverkuil@xs4all.nl>
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License
7
* as published by the Free Software Foundation; either version 2
8
* of the License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21
#include "general-tab.h"
22
#include <libv4l2util.h>
29
GeneralTab::GeneralTab(const QString &device, v4l2 &fd, int n, QWidget *parent) :
37
m_vidCapFormats(NULL),
43
setSizeConstraint(QLayout::SetMinimumSize);
45
if (querycap(m_querycap)) {
47
addLabel(device + (useWrapper() ? " (wrapped)" : ""), Qt::AlignLeft);
50
addLabel((char *)m_querycap.driver, Qt::AlignLeft);
53
addLabel((char *)m_querycap.card, Qt::AlignLeft);
56
addLabel((char *)m_querycap.bus_info, Qt::AlignLeft);
62
if (enum_input(vin, true)) {
64
m_videoInput = new QComboBox(parent);
66
m_videoInput->addItem((char *)vin.name);
67
} while (enum_input(vin));
68
addWidget(m_videoInput);
69
connect(m_videoInput, SIGNAL(activated(int)), SLOT(inputChanged(int)));
74
if (enum_output(vout, true)) {
76
m_videoOutput = new QComboBox(parent);
78
m_videoOutput->addItem((char *)vout.name);
79
} while (enum_output(vout));
80
addWidget(m_videoOutput);
81
connect(m_videoOutput, SIGNAL(activated(int)), SLOT(outputChanged(int)));
86
if (enum_audio(vaudio, true)) {
87
addLabel("Input Audio");
88
m_audioInput = new QComboBox(parent);
90
m_audioInput->addItem((char *)vaudio.name);
91
} while (enum_audio(vaudio));
92
addWidget(m_audioInput);
93
connect(m_audioInput, SIGNAL(activated(int)), SLOT(inputAudioChanged(int)));
97
v4l2_audioout vaudout;
98
if (enum_audout(vaudout, true)) {
99
addLabel("Output Audio");
100
m_audioOutput = new QComboBox(parent);
102
m_audioOutput->addItem((char *)vaudout.name);
103
} while (enum_audout(vaudout));
104
addWidget(m_audioOutput);
105
connect(m_audioOutput, SIGNAL(activated(int)), SLOT(outputAudioChanged(int)));
110
if (enum_std(vs, true)) {
111
addLabel("TV Standard");
112
m_tvStandard = new QComboBox(parent);
114
m_tvStandard->addItem((char *)vs.name);
115
} while (enum_std(vs));
116
addWidget(m_tvStandard);
117
connect(m_tvStandard, SIGNAL(activated(int)), SLOT(standardChanged(int)));
122
m_freq = new QSpinBox(parent);
123
m_freq->setMinimum(m_tuner.rangelow);
124
m_freq->setMaximum(m_tuner.rangehigh);
125
m_freq->setWhatsThis(QString("Frequency\nLow: %1\nHigh: %2")
126
.arg(m_tuner.rangelow).arg(m_tuner.rangehigh));
127
connect(m_freq, SIGNAL(valueChanged(int)), SLOT(freqChanged(int)));
129
addLabel("Frequency");
132
addLabel("Frequency Table");
133
m_freqTable = new QComboBox(parent);
134
for (int i = 0; v4l2_channel_lists[i].name; i++) {
135
m_freqTable->addItem(v4l2_channel_lists[i].name);
137
addWidget(m_freqTable);
138
connect(m_freqTable, SIGNAL(activated(int)), SLOT(freqTableChanged(int)));
140
addLabel("Channels");
141
m_freqChannel = new QComboBox(parent);
142
m_freqChannel->setSizeAdjustPolicy(QComboBox::AdjustToContents);
143
addWidget(m_freqChannel);
144
connect(m_freqChannel, SIGNAL(activated(int)), SLOT(freqChannelChanged(int)));
149
addLabel("Capture Image Formats");
150
m_vidCapFormats = new QComboBox(parent);
151
if (enum_fmt_cap(fmt, true)) {
153
m_vidCapFormats->addItem(pixfmt2s(fmt.pixelformat) +
154
" - " + (const char *)fmt.description);
155
} while (enum_fmt_cap(fmt));
157
addWidget(m_vidCapFormats);
158
connect(m_vidCapFormats, SIGNAL(activated(int)), SLOT(vidCapFormatChanged(int)));
160
addLabel("Frame Width");
161
m_frameWidth = new QSpinBox(parent);
162
addWidget(m_frameWidth);
163
connect(m_frameWidth, SIGNAL(editingFinished()), SLOT(frameWidthChanged()));
164
addLabel("Frame Height");
165
m_frameHeight = new QSpinBox(parent);
166
addWidget(m_frameHeight);
167
connect(m_frameHeight, SIGNAL(editingFinished()), SLOT(frameHeightChanged()));
169
addLabel("Frame Size");
170
m_frameSize = new QComboBox(parent);
171
m_frameSize->setSizeAdjustPolicy(QComboBox::AdjustToContents);
172
addWidget(m_frameSize);
173
connect(m_frameSize, SIGNAL(activated(int)), SLOT(frameSizeChanged(int)));
175
addLabel("Frame Interval");
176
m_frameInterval = new QComboBox(parent);
177
m_frameInterval->setSizeAdjustPolicy(QComboBox::AdjustToContents);
178
addWidget(m_frameInterval);
179
connect(m_frameInterval, SIGNAL(activated(int)), SLOT(frameIntervalChanged(int)));
181
updateVidCapFormat();
183
if (caps() & V4L2_CAP_VIDEO_OUTPUT) {
184
addLabel("Output Image Formats");
185
m_vidOutFormats = new QComboBox(parent);
186
if (enum_fmt_out(fmt, true)) {
188
m_vidOutFormats->addItem(pixfmt2s(fmt.pixelformat) +
189
" - " + (const char *)fmt.description);
190
} while (enum_fmt_out(fmt));
192
addWidget(m_vidOutFormats);
193
connect(m_vidOutFormats, SIGNAL(activated(int)), SLOT(vidOutFormatChanged(int)));
196
addLabel("Capture Method");
197
m_capMethods = new QComboBox(parent);
198
if (m_querycap.capabilities & V4L2_CAP_STREAMING) {
199
v4l2_requestbuffers reqbuf;
201
if (reqbufs_user_cap(reqbuf, 1))
202
m_capMethods->addItem("User pointer I/O", QVariant(methodUser));
204
if (reqbufs_mmap_cap(reqbuf, 1))
205
m_capMethods->addItem("Memory mapped I/O", QVariant(methodMmap));
207
if (m_querycap.capabilities & V4L2_CAP_READWRITE) {
208
m_capMethods->addItem("read()", QVariant(methodRead));
210
addWidget(m_capMethods);
212
QGridLayout::addWidget(new QWidget(parent), rowCount(), 0, 1, n);
213
setRowStretch(rowCount() - 1, 1);
216
void GeneralTab::addWidget(QWidget *w, Qt::Alignment align)
218
QGridLayout::addWidget(w, m_row, m_col, align | Qt::AlignVCenter);
220
if (m_col == m_cols) {
226
CapMethod GeneralTab::capMethod()
228
return (CapMethod)m_capMethods->itemData(m_capMethods->currentIndex()).toInt();
231
void GeneralTab::inputChanged(int input)
236
if (m_audioInput && g_audio(vaudio)) {
237
m_audioInput->setCurrentIndex(vaudio.index);
243
void GeneralTab::outputChanged(int output)
249
void GeneralTab::inputAudioChanged(int input)
255
void GeneralTab::outputAudioChanged(int output)
261
void GeneralTab::standardChanged(int std)
265
enum_std(vs, true, std);
270
void GeneralTab::freqTableChanged(int)
273
freqChannelChanged(0);
276
void GeneralTab::freqChannelChanged(int idx)
278
m_freq->setValue((int)(v4l2_channel_lists[m_freqTable->currentIndex()].list[idx].freq / 62.5));
281
void GeneralTab::freqChanged(int val)
286
void GeneralTab::vidCapFormatChanged(int idx)
290
enum_fmt_cap(desc, true, idx);
295
fmt.fmt.pix.pixelformat = desc.pixelformat;
298
updateVidCapFormat();
301
void GeneralTab::frameWidthChanged()
304
int val = m_frameWidth->value();
307
fmt.fmt.pix.width = val;
308
if (try_fmt(fmt) && s_fmt(fmt)) {
309
m_width = fmt.fmt.pix.width;
310
m_frameWidth->setValue(m_width);
314
void GeneralTab::frameHeightChanged()
317
int val = m_frameHeight->value();
320
fmt.fmt.pix.height = val;
321
if (try_fmt(fmt) && s_fmt(fmt)) {
322
m_height = fmt.fmt.pix.height;
323
m_frameHeight->setValue(m_height);
327
void GeneralTab::frameSizeChanged(int idx)
329
v4l2_frmsizeenum frmsize;
331
if (enum_framesizes(frmsize, m_pixelformat, idx)) {
332
m_width = frmsize.discrete.width;
333
m_height = frmsize.discrete.height;
338
fmt.fmt.pix.width = m_width;
339
fmt.fmt.pix.height = m_height;
345
void GeneralTab::frameIntervalChanged(int idx)
347
v4l2_frmivalenum frmival;
349
if (enum_frameintervals(frmival, m_pixelformat, m_width, m_height, idx)) {
354
void GeneralTab::vidOutFormatChanged(int idx)
358
enum_fmt_out(desc, true, idx);
363
fmt.fmt.pix.pixelformat = desc.pixelformat;
366
updateVidOutFormat();
369
void GeneralTab::updateVideoInput()
374
m_videoInput->setCurrentIndex(input);
377
void GeneralTab::updateVideoOutput()
382
m_videoOutput->setCurrentIndex(output);
385
void GeneralTab::updateAudioInput()
391
m_audioInput->setCurrentIndex(audio.index);
392
if (audio.capability & V4L2_AUDCAP_STEREO)
393
what = "stereo input";
396
if (audio.capability & V4L2_AUDCAP_AVL)
398
if (audio.mode & V4L2_AUDMODE_AVL)
399
what += ", AVL is on";
400
m_audioInput->setWhatsThis(what);
403
void GeneralTab::updateAudioOutput()
408
m_audioOutput->setCurrentIndex(audio.index);
411
void GeneralTab::updateStandard()
418
if (enum_std(vs, true)) {
422
} while (enum_std(vs));
425
if (enum_std(vs, true)) {
429
} while (enum_std(vs));
432
if ((vs.id & std) == 0)
434
m_tvStandard->setCurrentIndex(vs.index);
435
what.sprintf("TV Standard (0x%llX)\n"
436
"Frame period: %f (%d/%d)\n"
437
"Frame lines: %d", (long long int)std,
438
(double)vs.frameperiod.numerator / vs.frameperiod.denominator,
439
vs.frameperiod.numerator, vs.frameperiod.denominator,
441
m_tvStandard->setWhatsThis(what);
444
void GeneralTab::updateFreq()
449
m_freq->setValue(f.frequency);
452
void GeneralTab::updateFreqChannel()
454
m_freqChannel->clear();
455
int tbl = m_freqTable->currentIndex();
456
const struct v4l2_channel_list *list = v4l2_channel_lists[tbl].list;
457
for (unsigned i = 0; i < v4l2_channel_lists[tbl].count; i++)
458
m_freqChannel->addItem(list[i].name);
461
void GeneralTab::updateVidCapFormat()
467
m_pixelformat = fmt.fmt.pix.pixelformat;
468
if (enum_fmt_cap(desc, true)) {
470
if (desc.pixelformat == fmt.fmt.pix.pixelformat)
472
} while (enum_fmt_cap(desc));
474
if (desc.pixelformat != fmt.fmt.pix.pixelformat)
476
m_vidCapFormats->setCurrentIndex(desc.index);
477
updateFrameSize(fmt.fmt.pix.width, fmt.fmt.pix.height);
480
void GeneralTab::updateFrameSize(unsigned w, unsigned h)
482
v4l2_frmsizeenum frmsize;
485
m_frameSize->clear();
487
ok = enum_framesizes(frmsize, m_pixelformat);
488
if (ok && frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
490
m_frameSize->addItem(QString("%1x%2")
491
.arg(frmsize.discrete.width).arg(frmsize.discrete.height));
492
if (frmsize.discrete.width == w && frmsize.discrete.height == h)
493
m_frameSize->setCurrentIndex(frmsize.index);
494
} while (enum_framesizes(frmsize));
496
m_frameWidth->setEnabled(false);
497
m_frameHeight->setEnabled(false);
498
m_frameSize->setEnabled(true);
499
updateFrameInterval(w, h);
503
frmsize.stepwise.min_width = 8;
504
frmsize.stepwise.max_width = 1920;
505
frmsize.stepwise.step_width = 1;
506
frmsize.stepwise.min_height = 8;
507
frmsize.stepwise.max_height = 1200;
508
frmsize.stepwise.step_height = 1;
510
m_frameWidth->setEnabled(true);
511
m_frameHeight->setEnabled(true);
512
m_frameSize->setEnabled(false);
513
m_frameWidth->setMinimum(frmsize.stepwise.min_width);
514
m_frameWidth->setMaximum(frmsize.stepwise.max_width);
515
m_frameWidth->setSingleStep(frmsize.stepwise.step_width);
516
m_frameWidth->setValue(w);
517
m_frameHeight->setMinimum(frmsize.stepwise.min_height);
518
m_frameHeight->setMaximum(frmsize.stepwise.max_height);
519
m_frameHeight->setSingleStep(frmsize.stepwise.step_height);
520
m_frameHeight->setValue(h);
521
updateFrameInterval(w, h);
524
void GeneralTab::updateFrameInterval(unsigned w, unsigned h)
526
v4l2_frmivalenum frmival;
529
m_frameInterval->clear();
531
ok = enum_frameintervals(frmival, m_pixelformat, w, h);
532
if (ok && frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
534
m_frameInterval->addItem(QString("%1 fps")
535
.arg((double)frmival.discrete.denominator / frmival.discrete.numerator));
536
} while (enum_frameintervals(frmival));
540
void GeneralTab::updateVidOutFormat()
546
if (enum_fmt_out(desc, true)) {
548
if (desc.pixelformat == fmt.fmt.pix.pixelformat)
550
} while (enum_fmt_out(desc));
552
if (desc.pixelformat != fmt.fmt.pix.pixelformat)
554
m_vidCapFormats->setCurrentIndex(desc.index);