work around an issue with the connection dialog for now
[harmattan/cameraplus] / lib / qtcamscanner.cpp
1 #include "qtcamscanner.h"
2 #include "qtcamconfig.h"
3 #include <QDir>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7 #include <linux/videodev2.h>
8 #include <sys/ioctl.h>
9 #include <unistd.h>
10 #include <gst/gst.h>
11
12 class QtCamScannerPrivate {
13 public:
14   void scanEnum();
15   void scanV4l2();
16
17   QtCamConfig *conf;
18   QList<QPair<QString, QVariant> > devices;
19 };
20
21 void QtCamScannerPrivate::scanEnum() {
22   // Too bad there's no way to get the values of an enum without creating the element :(
23   GstElement *elem = gst_element_factory_make(conf->videoSource().toAscii(), NULL);
24   if (!elem) {
25     return;
26   }
27
28   GParamSpec *spec = g_object_class_find_property(G_OBJECT_GET_CLASS(elem),
29                                                   conf->deviceScannerProperty().toAscii());
30   if (!spec) {
31     gst_object_unref(elem);
32     return;
33   }
34
35   if (!G_IS_PARAM_SPEC_ENUM(spec)) {
36     gst_object_unref(elem);
37     return;
38   }
39
40   GParamSpecEnum *e = G_PARAM_SPEC_ENUM(spec);
41   // First add the default:
42   devices << qMakePair<QString, QVariant>(e->enum_class->values[e->default_value].value_name,
43                                           QByteArray::number(e->default_value));
44
45   for (int x = e->enum_class->minimum; x <= e->enum_class->maximum; x++) {
46     if (x != e->default_value) {
47       devices << qMakePair<QString, QVariant>(e->enum_class->values[x].value_name,
48                                               QByteArray::number(x));
49     }
50   }
51
52   gst_object_unref(elem);
53 }
54
55 void QtCamScannerPrivate::scanV4l2() {
56   QDir d("/dev/", "video?", QDir::Name | QDir::IgnoreCase, QDir::System);
57
58   QStringList entries = d.entryList();
59
60   foreach (const QString& dv, entries) {
61     QString dev = d.absoluteFilePath(dv);
62     struct v4l2_capability cap;
63     memset(&cap, 0x0, sizeof(cap));
64
65     int fd = open(dev.toLocal8Bit().data(), O_RDONLY);
66     if (fd == -1) {
67       continue;
68     }
69
70     if (ioctl(fd, VIDIOC_QUERYCAP, &cap) != 0) {
71       close(fd);
72       continue;
73     }
74
75     close(fd);
76
77     if (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) {
78       devices << qMakePair<QString, QVariant>((char *)cap.card, dev.toLocal8Bit());
79     }
80   }
81 }
82
83 QtCamScanner::QtCamScanner(QtCamConfig *conf, QObject *parent) :
84   QObject(parent), d_ptr(new QtCamScannerPrivate) {
85
86   d_ptr->conf = conf;
87 }
88
89 QtCamScanner::~QtCamScanner() {
90   delete d_ptr; d_ptr = 0;
91 }
92
93 void QtCamScanner::refresh() {
94   d_ptr->devices.clear();
95
96   if (d_ptr->conf->deviceScannerType() == SCANNER_TYPE_ENUM) {
97     d_ptr->scanEnum();
98   }
99   else {
100     d_ptr->scanV4l2();
101   }
102 }
103
104 QList<QPair<QString, QVariant> > QtCamScanner::devices() const {
105   return d_ptr->devices;
106 }