Logo Search packages:      
Sourcecode: v4l-utils version File versions  Download package

general-tab.cpp

/* qv4l2: a control panel controlling v4l2 devices.
 *
 * Copyright (C) 2006 Hans Verkuil <hverkuil@xs4all.nl>
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */


#include "general-tab.h"
#include <libv4l2util.h>

#include <QSpinBox>
#include <QComboBox>

#include <errno.h>

GeneralTab::GeneralTab(const QString &device, v4l2 &fd, int n, QWidget *parent) :
      QGridLayout(parent),
      v4l2(fd),
      m_row(0),
      m_col(0),
      m_cols(n),
      m_audioInput(NULL),
      m_freq(NULL),
      m_vidCapFormats(NULL),
      m_frameSize(NULL),
      m_vidOutFormats(NULL)
{
      setSpacing(3);

      setSizeConstraint(QLayout::SetMinimumSize);

      if (querycap(m_querycap)) {
            addLabel("Device:");
            addLabel(device + (useWrapper() ? " (wrapped)" : ""), Qt::AlignLeft);

            addLabel("Driver:");
            addLabel((char *)m_querycap.driver, Qt::AlignLeft);

            addLabel("Card:");
            addLabel((char *)m_querycap.card, Qt::AlignLeft);

            addLabel("Bus:");
            addLabel((char *)m_querycap.bus_info, Qt::AlignLeft);
      }

      g_tuner(m_tuner);

      v4l2_input vin;
      if (enum_input(vin, true)) {
            addLabel("Input");
            m_videoInput = new QComboBox(parent);
            do {
                  m_videoInput->addItem((char *)vin.name);
            } while (enum_input(vin));
            addWidget(m_videoInput);
            connect(m_videoInput, SIGNAL(activated(int)), SLOT(inputChanged(int)));
            updateVideoInput();
      }

      v4l2_output vout;
      if (enum_output(vout, true)) {
            addLabel("Output");
            m_videoOutput = new QComboBox(parent);
            do {
                  m_videoOutput->addItem((char *)vout.name);
            } while (enum_output(vout));
            addWidget(m_videoOutput);
            connect(m_videoOutput, SIGNAL(activated(int)), SLOT(outputChanged(int)));
            updateVideoOutput();
      }

      v4l2_audio vaudio;
      if (enum_audio(vaudio, true)) {
            addLabel("Input Audio");
            m_audioInput = new QComboBox(parent);
            do {
                  m_audioInput->addItem((char *)vaudio.name);
            } while (enum_audio(vaudio));
            addWidget(m_audioInput);
            connect(m_audioInput, SIGNAL(activated(int)), SLOT(inputAudioChanged(int)));
            updateAudioInput();
      }

      v4l2_audioout vaudout;
      if (enum_audout(vaudout, true)) {
            addLabel("Output Audio");
            m_audioOutput = new QComboBox(parent);
            do {
                  m_audioOutput->addItem((char *)vaudout.name);
            } while (enum_audout(vaudout));
            addWidget(m_audioOutput);
            connect(m_audioOutput, SIGNAL(activated(int)), SLOT(outputAudioChanged(int)));
            updateAudioOutput();
      }

      v4l2_standard vs;
      if (enum_std(vs, true)) {
            addLabel("TV Standard");
            m_tvStandard = new QComboBox(parent);
            do {
                  m_tvStandard->addItem((char *)vs.name);
            } while (enum_std(vs));
            addWidget(m_tvStandard);
            connect(m_tvStandard, SIGNAL(activated(int)), SLOT(standardChanged(int)));
            updateStandard();
      }

      if (m_tuner.type) {
            m_freq = new QSpinBox(parent);
            m_freq->setMinimum(m_tuner.rangelow);
            m_freq->setMaximum(m_tuner.rangehigh);
            m_freq->setWhatsThis(QString("Frequency\nLow: %1\nHigh: %2")
                        .arg(m_tuner.rangelow).arg(m_tuner.rangehigh));
            connect(m_freq, SIGNAL(valueChanged(int)), SLOT(freqChanged(int)));
            updateFreq();
            addLabel("Frequency");
            addWidget(m_freq);

            addLabel("Frequency Table");
            m_freqTable = new QComboBox(parent);
            for (int i = 0; v4l2_channel_lists[i].name; i++) {
                  m_freqTable->addItem(v4l2_channel_lists[i].name);
            }
            addWidget(m_freqTable);
            connect(m_freqTable, SIGNAL(activated(int)), SLOT(freqTableChanged(int)));

            addLabel("Channels");
            m_freqChannel = new QComboBox(parent);
            m_freqChannel->setSizeAdjustPolicy(QComboBox::AdjustToContents);
            addWidget(m_freqChannel);
            connect(m_freqChannel, SIGNAL(activated(int)), SLOT(freqChannelChanged(int)));
            updateFreqChannel();
      }

      v4l2_fmtdesc fmt;
      addLabel("Capture Image Formats");
      m_vidCapFormats = new QComboBox(parent);
      if (enum_fmt_cap(fmt, true)) {
            do {
                  m_vidCapFormats->addItem(pixfmt2s(fmt.pixelformat) +
                              " - " + (const char *)fmt.description);
            } while (enum_fmt_cap(fmt));
      }
      addWidget(m_vidCapFormats);
      connect(m_vidCapFormats, SIGNAL(activated(int)), SLOT(vidCapFormatChanged(int)));

      addLabel("Frame Width");
      m_frameWidth = new QSpinBox(parent);
      addWidget(m_frameWidth);
      connect(m_frameWidth, SIGNAL(editingFinished()), SLOT(frameWidthChanged()));
      addLabel("Frame Height");
      m_frameHeight = new QSpinBox(parent);
      addWidget(m_frameHeight);
      connect(m_frameHeight, SIGNAL(editingFinished()), SLOT(frameHeightChanged()));

      addLabel("Frame Size");
      m_frameSize = new QComboBox(parent);
      m_frameSize->setSizeAdjustPolicy(QComboBox::AdjustToContents);
      addWidget(m_frameSize);
      connect(m_frameSize, SIGNAL(activated(int)), SLOT(frameSizeChanged(int)));

      addLabel("Frame Interval");
      m_frameInterval = new QComboBox(parent);
      m_frameInterval->setSizeAdjustPolicy(QComboBox::AdjustToContents);
      addWidget(m_frameInterval);
      connect(m_frameInterval, SIGNAL(activated(int)), SLOT(frameIntervalChanged(int)));

      updateVidCapFormat();

      if (caps() & V4L2_CAP_VIDEO_OUTPUT) {
            addLabel("Output Image Formats");
            m_vidOutFormats = new QComboBox(parent);
            if (enum_fmt_out(fmt, true)) {
                  do {
                        m_vidOutFormats->addItem(pixfmt2s(fmt.pixelformat) +
                                    " - " + (const char *)fmt.description);
                  } while (enum_fmt_out(fmt));
            }
            addWidget(m_vidOutFormats);
            connect(m_vidOutFormats, SIGNAL(activated(int)), SLOT(vidOutFormatChanged(int)));
      }

      addLabel("Capture Method");
      m_capMethods = new QComboBox(parent);
      if (m_querycap.capabilities & V4L2_CAP_STREAMING) {
            v4l2_requestbuffers reqbuf;

            if (reqbufs_user_cap(reqbuf, 1))
                  m_capMethods->addItem("User pointer I/O", QVariant(methodUser));

            if (reqbufs_mmap_cap(reqbuf, 1))
                  m_capMethods->addItem("Memory mapped I/O", QVariant(methodMmap));
      }
      if (m_querycap.capabilities & V4L2_CAP_READWRITE) {
            m_capMethods->addItem("read()", QVariant(methodRead));
      }
      addWidget(m_capMethods);

      QGridLayout::addWidget(new QWidget(parent), rowCount(), 0, 1, n);
      setRowStretch(rowCount() - 1, 1);
}

void GeneralTab::addWidget(QWidget *w, Qt::Alignment align)
{
      QGridLayout::addWidget(w, m_row, m_col, align | Qt::AlignVCenter);
      m_col++;
      if (m_col == m_cols) {
            m_col = 0;
            m_row++;
      }
}

CapMethod GeneralTab::capMethod()
{
      return (CapMethod)m_capMethods->itemData(m_capMethods->currentIndex()).toInt();
}

void GeneralTab::inputChanged(int input)
{
      s_input(input);

      v4l2_audio vaudio;
      if (m_audioInput && g_audio(vaudio)) {
            m_audioInput->setCurrentIndex(vaudio.index);
            updateAudioInput();
      }
      updateVideoInput();
}

void GeneralTab::outputChanged(int output)
{
      s_output(output);
      updateVideoOutput();
}

void GeneralTab::inputAudioChanged(int input)
{
      s_audio(input);
      updateAudioInput();
}

void GeneralTab::outputAudioChanged(int output)
{
      s_audout(output);
      updateAudioOutput();
}

void GeneralTab::standardChanged(int std)
{
      v4l2_standard vs;

      enum_std(vs, true, std);
      s_std(vs.id);
      updateStandard();
}

void GeneralTab::freqTableChanged(int)
{
      updateFreqChannel();
      freqChannelChanged(0);
}

void GeneralTab::freqChannelChanged(int idx)
{
      m_freq->setValue((int)(v4l2_channel_lists[m_freqTable->currentIndex()].list[idx].freq / 62.5));
}

void GeneralTab::freqChanged(int val)
{
      s_frequency(val);
}

void GeneralTab::vidCapFormatChanged(int idx)
{
      v4l2_fmtdesc desc;

      enum_fmt_cap(desc, true, idx);

      v4l2_format fmt;

      g_fmt_cap(fmt);
      fmt.fmt.pix.pixelformat = desc.pixelformat;
      try_fmt(fmt);
      s_fmt(fmt);
      updateVidCapFormat();
}

void GeneralTab::frameWidthChanged()
{
      v4l2_format fmt;
      int val = m_frameWidth->value();

      g_fmt_cap(fmt);
      fmt.fmt.pix.width = val;
      if (try_fmt(fmt) && s_fmt(fmt)) {
            m_width = fmt.fmt.pix.width;
            m_frameWidth->setValue(m_width);
      }
}

void GeneralTab::frameHeightChanged()
{
      v4l2_format fmt;
      int val = m_frameHeight->value();

      g_fmt_cap(fmt);
      fmt.fmt.pix.height = val;
      if (try_fmt(fmt) && s_fmt(fmt)) {
            m_height = fmt.fmt.pix.height;
            m_frameHeight->setValue(m_height);
      }
}

void GeneralTab::frameSizeChanged(int idx)
{
      v4l2_frmsizeenum frmsize;

      if (enum_framesizes(frmsize, m_pixelformat, idx)) {
            m_width = frmsize.discrete.width;
            m_height = frmsize.discrete.height;

            v4l2_format fmt;

            g_fmt_cap(fmt);
            fmt.fmt.pix.width = m_width;
            fmt.fmt.pix.height = m_height;
            try_fmt(fmt);
            s_fmt(fmt);
      }
}

void GeneralTab::frameIntervalChanged(int idx)
{
      v4l2_frmivalenum frmival;

      if (enum_frameintervals(frmival, m_pixelformat, m_width, m_height, idx)) {
            // TODO
      }
}

void GeneralTab::vidOutFormatChanged(int idx)
{
      v4l2_fmtdesc desc;

      enum_fmt_out(desc, true, idx);

      v4l2_format fmt;

      g_fmt_out(fmt);
      fmt.fmt.pix.pixelformat = desc.pixelformat;
      try_fmt(fmt);
      s_fmt(fmt);
      updateVidOutFormat();
}

void GeneralTab::updateVideoInput()
{
      int input;

      g_input(input);
      m_videoInput->setCurrentIndex(input);
}

void GeneralTab::updateVideoOutput()
{
      int output;

      g_output(output);
      m_videoOutput->setCurrentIndex(output);
}

void GeneralTab::updateAudioInput()
{
      v4l2_audio audio;
      QString what;

      g_audio(audio);
      m_audioInput->setCurrentIndex(audio.index);
      if (audio.capability & V4L2_AUDCAP_STEREO)
            what = "stereo input";
      else
            what = "mono input";
      if (audio.capability & V4L2_AUDCAP_AVL)
            what += ", has AVL";
      if (audio.mode & V4L2_AUDMODE_AVL)
            what += ", AVL is on";
      m_audioInput->setWhatsThis(what);
}

void GeneralTab::updateAudioOutput()
{
      v4l2_audioout audio;

      g_audout(audio);
      m_audioOutput->setCurrentIndex(audio.index);
}

void GeneralTab::updateStandard()
{
      v4l2_std_id std;
      v4l2_standard vs;
      QString what;

      g_std(std);
      if (enum_std(vs, true)) {
            do {
                  if (vs.id == std)
                        break;
            } while (enum_std(vs));
      }
      if (vs.id != std) {
            if (enum_std(vs, true)) {
                  do {
                        if (vs.id & std)
                              break;
                  } while (enum_std(vs));
            }
      }
      if ((vs.id & std) == 0)
            return;
      m_tvStandard->setCurrentIndex(vs.index);
      what.sprintf("TV Standard (0x%llX)\n"
            "Frame period: %f (%d/%d)\n"
            "Frame lines: %d", (long long int)std,
            (double)vs.frameperiod.numerator / vs.frameperiod.denominator,
            vs.frameperiod.numerator, vs.frameperiod.denominator,
            vs.framelines);
      m_tvStandard->setWhatsThis(what);
}

void GeneralTab::updateFreq()
{
      v4l2_frequency f;

      g_frequency(f);
      m_freq->setValue(f.frequency);
}

void GeneralTab::updateFreqChannel()
{
      m_freqChannel->clear();
      int tbl = m_freqTable->currentIndex();
      const struct v4l2_channel_list *list = v4l2_channel_lists[tbl].list;
      for (unsigned i = 0; i < v4l2_channel_lists[tbl].count; i++)
            m_freqChannel->addItem(list[i].name);
}

void GeneralTab::updateVidCapFormat()
{
      v4l2_fmtdesc desc;
      v4l2_format fmt;

      g_fmt_cap(fmt);
      m_pixelformat = fmt.fmt.pix.pixelformat;
      if (enum_fmt_cap(desc, true)) {
            do {
                  if (desc.pixelformat == fmt.fmt.pix.pixelformat)
                        break;
            } while (enum_fmt_cap(desc));
      }
      if (desc.pixelformat != fmt.fmt.pix.pixelformat)
            return;
      m_vidCapFormats->setCurrentIndex(desc.index);
      updateFrameSize(fmt.fmt.pix.width, fmt.fmt.pix.height);
}

void GeneralTab::updateFrameSize(unsigned w, unsigned h)
{
      v4l2_frmsizeenum frmsize;
      bool ok = false;

      m_frameSize->clear();

      ok = enum_framesizes(frmsize, m_pixelformat);
      if (ok && frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {
            do {
                  m_frameSize->addItem(QString("%1x%2")
                        .arg(frmsize.discrete.width).arg(frmsize.discrete.height));
                  if (frmsize.discrete.width == w && frmsize.discrete.height == h)
                        m_frameSize->setCurrentIndex(frmsize.index);
            } while (enum_framesizes(frmsize));

            m_frameWidth->setEnabled(false);
            m_frameHeight->setEnabled(false);
            m_frameSize->setEnabled(true);
            updateFrameInterval(w, h);
            return;
      }
      if (!ok) {
            frmsize.stepwise.min_width = 8;
            frmsize.stepwise.max_width = 1920;
            frmsize.stepwise.step_width = 1;
            frmsize.stepwise.min_height = 8;
            frmsize.stepwise.max_height = 1200;
            frmsize.stepwise.step_height = 1;
      }
      m_frameWidth->setEnabled(true);
      m_frameHeight->setEnabled(true);
      m_frameSize->setEnabled(false);
      m_frameWidth->setMinimum(frmsize.stepwise.min_width);
      m_frameWidth->setMaximum(frmsize.stepwise.max_width);
      m_frameWidth->setSingleStep(frmsize.stepwise.step_width);
      m_frameWidth->setValue(w);
      m_frameHeight->setMinimum(frmsize.stepwise.min_height);
      m_frameHeight->setMaximum(frmsize.stepwise.max_height);
      m_frameHeight->setSingleStep(frmsize.stepwise.step_height);
      m_frameHeight->setValue(h);
      updateFrameInterval(w, h);
}

void GeneralTab::updateFrameInterval(unsigned w, unsigned h)
{
      v4l2_frmivalenum frmival;
      bool ok = false;

      m_frameInterval->clear();

      ok = enum_frameintervals(frmival, m_pixelformat, w, h);
      if (ok && frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
            do {
                  m_frameInterval->addItem(QString("%1 fps")
                        .arg((double)frmival.discrete.denominator / frmival.discrete.numerator));
            } while (enum_frameintervals(frmival));
      }
}

void GeneralTab::updateVidOutFormat()
{
      v4l2_fmtdesc desc;
      v4l2_format fmt;

      g_fmt_out(fmt);
      if (enum_fmt_out(desc, true)) {
            do {
                  if (desc.pixelformat == fmt.fmt.pix.pixelformat)
                        break;
            } while (enum_fmt_out(desc));
      }
      if (desc.pixelformat != fmt.fmt.pix.pixelformat)
            return;
      m_vidCapFormats->setCurrentIndex(desc.index);
}

Generated by  Doxygen 1.6.0   Back to index