File kaffeine-2.0.18_support_sundtek_devices.diff of Package KaffeineLeap15p6

diff --git a/.pc/applied-patches b/.pc/applied-patches
index e69de29..a9327a6 100644
--- a/.pc/applied-patches
+++ b/.pc/applied-patches
@@ -0,0 +1 @@
+kaffeine-2.0.18_support_sundtek_devices.diff
diff --git a/src/dvb/dvbdevice_linux.cpp b/src/dvb/dvbdevice_linux.cpp
index 6843137..81fd68b 100644
--- a/src/dvb/dvbdevice_linux.cpp
+++ b/src/dvb/dvbdevice_linux.cpp
@@ -27,8 +27,18 @@ extern "C" {
   #include <fcntl.h>
   #include <frontend.h>
   #include <poll.h>
-}
-
+  #include <sys/socket.h>
+  #include <sys/un.h>
+  #include <sys/types.h>
+  #include <sys/ioctl.h>
+  #include <sys/stat.h>
+  #include <dirent.h>
+  #include <sys/inotify.h>
+  #include <vector>
+  #include <stdlib.h>
+}
+
+#include <QDebug>
 #include <QFile>
 #include <QCheckBox>
 #include <QMessageLogger>
@@ -47,6 +57,148 @@ extern "C" {
 
 // krazy:excludeall=syscalls
 
+
+
+struct dvbdev {
+        time_t stctime;
+        char checked;
+        char adapter_name[50];
+        char node_name[75];
+        int adapternum;
+        char lnode[20];
+};
+
+class DvbDeviceMonitor : public QThread
+{
+public:
+        DvbDeviceMonitor(DvbLinuxDeviceManager *ddm)
+        {
+                this->ddm = ddm;
+        }
+        ~DvbDeviceMonitor()
+        {
+        }
+        void run() {
+                DIR *dvbdir, *adapterdirp;
+                struct dirent *dp, *dp2;
+                struct stat stbuf;
+                int adapter;
+                int rescan=0;
+                int rv;
+                int ifd;
+                int found=0;
+                char adapterdir[50];
+                char nodename[75];
+                char buffer[1024];
+                struct pollfd pfd;
+                char firstrun_complete=0;
+                std::vector<struct dvbdev*>adapterlist;
+                std::vector<struct dvbdev*>::iterator iter;
+
+		bzero(adapterdir, sizeof(adapterdir));
+		bzero(nodename, sizeof(nodename));
+		bzero(buffer, sizeof(buffer));
+
+                runstate = 1;
+
+                ifd = inotify_init();
+                inotify_add_watch(ifd, "/dev/dvb", IN_CREATE|IN_DELETE);
+                fcntl(ifd, F_SETFL, O_NONBLOCK);
+                pfd.fd = ifd;
+                pfd.events = POLLIN;
+
+                while(runstate) {
+                        if (firstrun_complete) {
+                                rv = poll(&pfd, 1, 100);
+                                switch (rv) {
+                                case -1:
+                                        break;
+                                case 0:
+                                        continue;
+                                default:
+                                        usleep(100000); /* give it some time to settle down */
+                                        while(read(ifd, buffer, 1024)>0);
+                                        break;
+                                }
+                        } else {
+                                firstrun_complete=1;
+                        }
+
+                        dvbdir = opendir("/dev/dvb");
+                        for (iter=adapterlist.begin();iter!=adapterlist.end();iter++) {
+                                (*iter)->checked=0;
+                        }
+                        if (dvbdir) {
+                                while((dp=readdir(dvbdir))!= 0) {
+                                        if (strcmp(dp->d_name, ".") == 0 ||
+                                            strcmp(dp->d_name, "..") == 0)
+                                                continue;
+                                        adapter = strtol(&dp->d_name[7], NULL, 10);
+                                        snprintf(adapterdir, 49, "/dev/dvb/%s", dp->d_name);
+                                        adapterdirp = opendir(adapterdir);
+                                        if (adapterdirp) {
+                                                while((dp2=readdir(adapterdirp))!=0) {
+                                                        found=0;
+                                                        if (strcmp(dp2->d_name, ".")==0 ||
+                                                                strcmp(dp2->d_name, "..")==0)
+                                                                continue;
+                                                        snprintf(nodename, 74, "/dev/dvb/%s/%s", dp->d_name, dp2->d_name);
+                                                        rv = stat(nodename, &stbuf);
+                                                        for (iter=adapterlist.begin();iter!=adapterlist.end();iter++) {
+                                                                if (strcmp((*iter)->node_name, nodename)==0 && (*iter)->stctime == stbuf.st_ctime) {
+                                                                        (*iter)->checked=1;
+                                                                        found=1;
+                                                                        break;
+                                                                }
+                                                        }
+                                                        if (found == 0) {
+                                                                struct dvbdev *dvbdev = (struct dvbdev*)calloc(1, sizeof(struct dvbdev));
+                                                                dvbdev->checked=1;
+                                                                dvbdev->stctime = stbuf.st_ctime;
+                                                                strcpy(dvbdev->adapter_name, dp->d_name);
+                                                                strcpy(dvbdev->node_name, nodename);
+                                                                dvbdev->adapternum = adapter;
+                                                                strcpy(dvbdev->lnode, dp2->d_name);
+                                                                adapterlist.push_back(dvbdev);
+                                                                ddm->componentAdded(dp2->d_name, adapter, 0);
+                                                        }
+
+                                                }
+                                                closedir(adapterdirp);
+                                        }
+                                }
+                                closedir(dvbdir);
+                        }
+                        do {
+                                rescan=0;
+                                for (iter=adapterlist.begin();iter!=adapterlist.end();iter++) {
+                                        if ((*iter)->checked==0) {
+                                                ddm->componentRemoved((*iter)->lnode, (*iter)->adapternum, 0);
+                                                free(*iter);
+                                                adapterlist.erase(iter);
+                                                rescan=1;
+                                                break;
+                                        }
+                                }
+                        } while (rescan!=0);
+                }
+        }
+        void stop() {
+                runstate = 0;
+                wait();
+        }
+private:
+        int runstate;
+        DvbLinuxDeviceManager *ddm;
+};
+
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__sun)
+#define MACHADDRESS "/tmp/.mediasocket"
+#else
+#define ADDRESS     "/de/sundtek/mediasocket"  /* addr to connect */
+#endif
+
+
 DvbLinuxDevice::DvbLinuxDevice(QObject *parent) : QThread(parent), ready(false), frontend(NULL),
 	enabled(false), dvrFd(-1), dvrBuffer(NULL, 0), cam(parent)
 {
@@ -95,10 +247,25 @@ bool DvbLinuxDevice::isReady() const
 	return ready;
 }
 
+extern "C" int dvb_fe_open_fname(struct dvb_v5_fe_parms *, char *fname, int flags);
+
 void DvbLinuxDevice::startDevice(const QString &deviceId_)
 {
 	Q_ASSERT(!ready);
-	struct dvb_v5_fe_parms *parms = dvb_fe_open2(adapter, index, verbose, 0, dvbv5_log);
+	struct dvb_v5_fe_parms *parms;
+	if (adapter == -1) {
+		int rv;
+		parms = dvb_fe_dummy(); //(struct dvb_v5_fe_parms*)calloc(1, sizeof(struct dvb_v5_fe_parms));
+		rv = dvb_fe_open_fname(parms, strdup((char*)frontendPath.toStdString().c_str()), O_RDWR);
+		if (rv) {
+			free(parms);
+			qCWarning(logDev, "Cannot open frontend %s", qPrintable(frontendPath));
+			return;
+		}
+	} else {
+		parms = dvb_fe_open2(adapter, index, verbose, 0, dvbv5_log);
+	}
+
 
 	if (!parms) {
 		qCWarning(logDev, "Cannot open frontend %s", qPrintable(frontendPath));
@@ -267,7 +434,18 @@ void DvbLinuxDevice::setDeviceEnabled(bool enabled_)
 bool DvbLinuxDevice::acquire()
 {
 	Q_ASSERT(enabled && (!dvbv5_parms) && (dvrFd < 0));
-	dvbv5_parms = dvb_fe_open2(adapter, index, verbose, 0, dvbv5_log);
+	if (adapter == -1) {
+		int rv;
+		dvbv5_parms = dvb_fe_dummy();
+		rv = dvb_fe_open_fname(dvbv5_parms, strdup((char*)frontendPath.toStdString().c_str()), O_RDWR);
+		if (rv) {
+			free (dvbv5_parms);
+			qCWarning(logDev, "Cannot open frontend %s", qPrintable(frontendPath));
+			return false;
+		}
+	} else {
+		dvbv5_parms = dvb_fe_open2(adapter, index, verbose, 0, dvbv5_log);
+	}
 
 	if (!dvbv5_parms) {
 		qCWarning(logDev, "Cannot open frontend %s", qPrintable(frontendPath));
@@ -1617,13 +1795,74 @@ void DvbLinuxDevice::run()
 
 DvbLinuxDeviceManager::DvbLinuxDeviceManager(QObject *parent) : QObject(parent)
 {
+        int fd;
+        int len;
+        int ret;
+        struct sockaddr_un saun;
 	QObject *notifier = Solid::DeviceNotifier::instance();
 	connect(notifier, SIGNAL(deviceAdded(QString)), this, SLOT(componentAdded(QString)));
 	connect(notifier, SIGNAL(deviceRemoved(QString)), this, SLOT(componentRemoved(QString)));
+        memset(&saun, 0x0, sizeof(struct sockaddr_un));
+        fd = socket(AF_UNIX, SOCK_STREAM, 0);
+        if (fd==-1) {
+		monitor = NULL;
+                return;
+	}
+        saun.sun_family = AF_UNIX;
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__sun)
+        strcpy(saun.sun_path, MACHADDRESS);
+        len = sizeof(saun.sun_family) + strlen(saun.sun_path)+1;
+#else
+        strcpy(&saun.sun_path[1], ADDRESS);
+        len = sizeof(saun.sun_family) + strlen(&saun.sun_path[1])+1;
+#endif
+        if ((ret=::connect(fd, (struct sockaddr*)&saun, len)) < 0) {
+                close(fd);
+		monitor = NULL;
+                return;
+        }
+	close(fd);
+	monitor = new DvbDeviceMonitor(this);
+	monitor->start();
 }
 
 DvbLinuxDeviceManager::~DvbLinuxDeviceManager()
 {
+	if (monitor)
+		monitor->stop();
+}
+
+
+void DvbLinuxDeviceManager::componentAdded(QString node, int adapter, int index) {
+	qDebug() << "component added" << node << adapter << index;
+	int deviceIndex = (adapter << 16) | index;
+	DvbLinuxDevice *device = devices.value(deviceIndex, NULL);
+	if (device == NULL) {
+		device = new DvbLinuxDevice(this);
+		devices.insert(deviceIndex, device);
+	}
+
+	if (node == "frontend0") {
+		device->frontendPath=QString("/dev/dvb/adapter%1/%2").arg(QString::number(adapter)).arg(node);
+		qDebug() << "found" << device->frontendPath;
+	} else if (node == "dvr0") {
+		device->dvrPath=QString("/dev/dvb/adapter%1/%2").arg(QString::number(adapter)).arg(node);
+	} else if (node == "demux0") {
+		device->demuxPath=QString("/dev/dvb/adapter%1/%2").arg(QString::number(adapter)).arg(node);
+	} else {
+		return;
+	}
+
+	if (!device->demuxPath.isEmpty() && !device->dvrPath.isEmpty() &&
+			!device->frontendPath.isEmpty()) {
+		device->adapter = -1;
+		device->index = index;
+		device->startDevice("");
+
+		if (device->isReady()) {
+			emit deviceAdded(device);
+		}
+	}
 }
 
 void DvbLinuxDeviceManager::doColdPlug()
openSUSE Build Service is sponsored by