Description: <short summary of the patch>
 TODO: Put a short summary on the line above and replace this paragraph
 with a longer explanation of this change. Complete the meta-information
 with other relevant fields (see below for details). To make it easier, the
 information below has been extracted from the changelog. Adjust it or drop
 it.
 .
 stopmotion (0.8.0-5) unstable; urgency=medium
 .
   * patch from Georges Khaznadar <georgesk@debian.org> for vgrabbj daemon
     mode return code (closes: #785459)
Author: Barak A. Pearlmutter <bap@debian.org>
Bug-Debian: https://bugs.debian.org/785459

---
The information above should follow the Patch Tagging Guidelines, please
checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here
are templates for supplementary fields that you might want to add:

Origin: <vendor|upstream|other>, <url of original patch>
Bug: <url in upstream bugtracker>
Bug-Debian: https://bugs.debian.org/<bugnumber>
Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber>
Forwarded: <no|not-needed|url proving that it has been forwarded>
Reviewed-By: <name and email of someone who approved the patch>
Last-Update: <YYYY-MM-DD>

--- stopmotion-0.8.0.orig/README
+++ stopmotion-0.8.0/README
@@ -7,7 +7,7 @@ See http://linuxstopmotion.org for more
 INSTALLATION
 ------------
 1) qmake
-2) make install
+2) sudo make install
 
 You need the following libraries installed to compile:
     - Qt4
@@ -39,13 +39,23 @@ DEVELOPMENT
 
 After qmake, the following make targets are available:
 
-make debug   # build a debug version of the project, called stopmotion-d
-make release # build a release version of the project, called stopmotion
-make         # build both debug and release versions
-make install # build and install the release version in /usr/local
-make test    # build and run the unit tests
+make           # build a release version of the project, called stopmotion
+make debug     # build a debug version of the project, called stopmotion-d
+make all       # build both debug and release versions
+make test      # build and run the unit tests
+make clean     # remove all build products
+make install   # install stopmotion
+make uninstall # remove installation
+
+To install in a specific location:
+
+qmake PREFIX=/specific/location
+sudo make install
 
-To install to a specific location (other than /usr/local):
+To put the files somewhere before copying them for installation (after qmake):
 
-qmake PREFIX=/path/to/installation
-make install
+make INSTALL_ROOT=/somewhere/writeable install
+cp -fr /somewhere/writeable/* /
+
+PREFIX is where the files will ultimately end up. make install will put them in
+$(INSTALL_ROOT)$(PREFIX)
--- stopmotion-0.8.0.orig/graphics/icons/windowicon.xpm
+++ stopmotion-0.8.0/graphics/icons/windowicon.xpm
@@ -1,5 +1,5 @@
 /* XPM */
-static char * windowicon[] = {
+static const char * windowicon[] = {
 "16 16 7 1",
 " 	c None",
 ".	c #D40000",
--- stopmotion-0.8.0.orig/src/presentation/frontends/nonguifrontend/nonguifrontend.cpp
+++ stopmotion-0.8.0/src/presentation/frontends/nonguifrontend/nonguifrontend.cpp
@@ -31,6 +31,7 @@
 #include <errno.h>
 #include <string>
 #include <string.h>
+#include <sstream>
 
 
 NonGUIFrontend::NonGUIFrontend(DomainFacade *facadePtr)
@@ -48,7 +49,8 @@ int NonGUIFrontend::run(int argc, char *
 }
 
 
-void NonGUIFrontend::showProgress(ProgressMessage message, int numOperations) {
+void NonGUIFrontend::showProgress(ProgressMessage message,
+		int /*numOperations*/) {
 	// sets the stdout to be unbuffered
 	setvbuf(stdout, NULL, _IONBF,0);
 	const char* infoText = "Please wait";
@@ -237,12 +239,13 @@ int NonGUIFrontend::checkFiles(const cha
 	if (dp) {
 		struct dirent *ep;
 		struct stat st;
-		char tmp[PATH_MAX] = {0};
+		std::stringstream path;
 
 		while ( (ep = readdir(dp)) ) {
-			snprintf(tmp, sizeof(tmp), "%s%s", directory, ep->d_name);
-			tmp[sizeof(tmp) - 1] = '\0';  // ensure null-terminated
-			stat(tmp, &st);
+			path.str("");
+			path << directory << ep->d_name;
+			std::string p(path.str());
+			stat(p.c_str(), &st);
 			// is a regular file, not a directory
 			if ( S_ISREG(st.st_mode) != 0) {
 				++numSuccessFull;
--- stopmotion-0.8.0.orig/src/presentation/frontends/qtfrontend/devicetab.cpp
+++ stopmotion-0.8.0/src/presentation/frontends/qtfrontend/devicetab.cpp
@@ -175,7 +175,6 @@ void DeviceTab::initialize()
 
 	if (numUserDevices > 0 ) {
 		deviceTable->setRowCount( numUserDevices + numAutoDetectedDevices );
-		const char *prop = 0;
 		int idx = 0;
 
 		for (int i = 0; i < numUserDevices; ++i) {
--- stopmotion-0.8.0.orig/src/presentation/frontends/qtfrontend/exporttab.cpp
+++ stopmotion-0.8.0/src/presentation/frontends/qtfrontend/exporttab.cpp
@@ -189,7 +189,6 @@ void ExportTab::initialize()
 
 	int numEncoders = pref->getPreference("numEncoders", 0);
 	encoderTable->setRowCount(numEncoders);
-	const char *prop = 0;
 	for (int i = 0; i < numEncoders; ++i) {
 		Preference name(QString("encoderName%1").arg(i).toLatin1().constData(),"");
 		encoderTable->setItem(i, 0, new QTableWidgetItem(name.get()) );
--- stopmotion-0.8.0.orig/src/presentation/frontends/qtfrontend/framebar/thumbview.cpp
+++ stopmotion-0.8.0/src/presentation/frontends/qtfrontend/framebar/thumbview.cpp
@@ -27,7 +27,7 @@
 
 ThumbView::ThumbView(FrameBar *frameBar, QWidget *parent, int number,
 		const char *name)
-	: QLabel(parent), frameBar(frameBar), number(number), refCount(1) {
+	: QLabel(parent), refCount(1), frameBar(frameBar), number(number) {
 	setObjectName(name);
 }
 
--- stopmotion-0.8.0.orig/src/presentation/frontends/qtfrontend/mainwindowgui.cpp
+++ stopmotion-0.8.0/src/presentation/frontends/qtfrontend/mainwindowgui.cpp
@@ -62,6 +62,7 @@
 
 #include <cstdlib>
 #include <unistd.h>
+#include <sstream>
 
 using namespace std;
 using namespace Qt;
@@ -920,20 +921,26 @@ void MainWindowGUI::exportToVideo()
 	}
 	else {
 		bool isCanceled = false;
-		char tmp[PATH_MAX];
+		std::stringstream key;
+		std::string k;
 		VideoEncoder enc;
 
-		sprintf(tmp, "startEncoder%d", active);
-		Preference start(tmp, "");
+		key << "startEncoder" << active;
+		k = key.str();
+		Preference start(k.c_str(), "");
 		enc.setStartCommand(start.get());
 
-		sprintf(tmp, "stopEncoder%d", active);
-		Preference stop(tmp, "");
+		key.str("");
+		key << "stopEncoder" << active;
+		k = key.str();
+		Preference stop(k.c_str(), "");
 		enc.setStopCommand(stop.get());
 
-		sprintf(tmp, "outputFile%d", active);
-		Preference output(tmp);
-		if (output.get()) {
+		key.str("");
+		key << "outputFile" << active;
+		k = key.str();
+		Preference output(k.c_str());
+		if (output.get() && *output.get()) {
 			enc.setOutputFile(output.get());
 		} else {
 			QString file = QFileDialog::
@@ -1138,7 +1145,6 @@ void MainWindowGUI::activateMenuOptions(
 void MainWindowGUI::createMostRecentMenu() {
 	mostRecentMenu->clear();
 	mostRecentMenu->setTitle(tr("Open &Recent"));
-	PreferencesTool* pref = PreferencesTool::get();
 	Preference first("mostRecent", "");
 	if (first.get() && access(first.get(), R_OK) == 0) {
 		mostRecentAct->setVisible(true);
--- stopmotion-0.8.0.orig/src/technical/audio/ossdriver.cpp
+++ stopmotion-0.8.0/src/technical/audio/ossdriver.cpp
@@ -119,7 +119,7 @@ bool OSSDriver::initialize()
 	// Storing the request and its argument
 	int initValues[2][4] = 
 	{ 
-		{SNDCTL_DSP_RESET, SNDCTL_DSP_SETFMT, SOUND_PCM_WRITE_CHANNELS, SOUND_PCM_WRITE_RATE},
+		{SNDCTL_DSP_RESET, SNDCTL_DSP_SETFMT, SNDCTL_DSP_CHANNELS, SNDCTL_DSP_SPEED},
 		{1, AFMT_S16_LE, 2, 44100} 
 	};
 	
--- stopmotion-0.8.0.orig/src/technical/grabber/commandlinegrabber.cpp
+++ stopmotion-0.8.0/src/technical/grabber/commandlinegrabber.cpp
@@ -77,28 +77,38 @@ bool CommandLineGrabber::setStopCommand(
 }
 
 
-bool CommandLineGrabber::init()
-{
+bool CommandLineGrabber::init() {
 	if (isProcess) {
 		if (startProcess != "") {
-			Logger::get().logDebug("Attemting to start process");
-			system(startProcess.c_str());
-			
-		}
-		else {
-			return false;
+			Logger::get().logDebug("Attempting to start process");
+			int r = system(startProcess.c_str());
+			if ((r != 0) && (r != 256)) {
+			        // r==256 is possible for vgrabbj in daemon mode
+				Logger::get().logFatal(
+						"Grab start process '%s' returned code %d",
+						startProcess.c_str(), r);
+				return true;
+			} else {
+				return true;
+			}
 		}
+		return false;
 	}
 	return true;
 }
 
 
-bool CommandLineGrabber::tearDown()
-{
-	Logger::get().logDebug("Attemting to shutt down process");
+bool CommandLineGrabber::tearDown() {
+	Logger::get().logDebug("Attempting to shutt down process");
 	if (stopProcess != "") {
-		system( stopProcess.c_str() );
-		return true;
+		int r = system( stopProcess.c_str() );
+		if (r != 0) {
+			Logger::get().logFatal(
+					"Grab stop process '%s' returned code %d",
+					stopProcess.c_str(), r);
+		} else {
+			return true;
+		}
 	}
 	return false;
 }
--- stopmotion-0.8.0.orig/src/technical/util.cpp
+++ stopmotion-0.8.0/src/technical/util.cpp
@@ -19,13 +19,12 @@
  ***************************************************************************/
 #include "src/technical/util.h"
 
-#include "src/technical/libng/grab-ng.h"
-
 #include <ext/stdio_filebuf.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/ioctl.h>
 #include <unistd.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -33,6 +32,10 @@
 #include <cassert>
 #include <istream>
 #include <ftw.h>
+#include <glob.h>
+#include <linux/videodev2.h>
+#include <sstream>
+#include <new>
 
 using namespace std;
 
@@ -161,67 +164,47 @@ bool Util::checkCommand(std::string* pat
 	return !bad && exitStatus < 2;
 }
 
+namespace {
+
+template <std::size_t S> void setString(std::string& output, const __u8 (&in)[S]) {
+	const char* p = reinterpret_cast<const char*>(in);
+	output.assign(p, strnlen(p, S));
+}
+
+bool getGrabberDevice(const char* dev, GrabberDevice& d) {
+	int fd;
+	struct v4l2_capability video_cap;
+
+	if((fd = open(dev, O_RDONLY)) == -1){
+		return false;
+	}
+
+	int vcrv = ioctl(fd, VIDIOC_QUERYCAP, &video_cap);
+	close(fd);
+	if (vcrv == -1)
+		return false;
+	if (!(video_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
+		return false;
+	d.device.assign(dev);
+	setString(d.name, video_cap.card);
+	setString(d.type, video_cap.driver);
+	return true;
+}
+}
 
 const vector<GrabberDevice> Util::getGrabberDevices() {
-	// Ensures ng_init() is called once
-	static int count = 0;
-	if (count++ == 0) {
-		ng_init();
-	}
-	
 	vector<GrabberDevice> devices;
-	const struct ng_vid_driver *driver = 0;
-	void *handle = 0;
-	struct stat st;
-	int fh    = -1;
-	int flags = -1;
-
-	for (int i = 0; ng_dev.video_scan[i] != 0; ++i) {
-		if (lstat(ng_dev.video_scan[i], &st) == -1) {
-			if (errno == ENOENT) {
-				continue;
-			}
-#ifndef NO_DEBUG
-			fprintf(stderr,"%s: %s\n",ng_dev.video_scan[i],strerror(errno));
-#endif
-			continue;
-		}
-
-		fh = open(ng_dev.video_scan[i], O_RDWR);
-		if (fh == -1) {
-			if (ENODEV == errno) {
-				continue;
-			}
-#ifndef NO_DEBUG
-			fprintf(stderr,"%s: %s\n",ng_dev.video_scan[i],strerror(errno));
-#endif
-			continue;
-		}
-		close(fh);
-
-		driver = ng_vid_open(ng_dev.video_scan[i], 0, 0, 0, &handle);
-		if (driver == 0) {
-#ifndef NO_DEBUG
-			fprintf(stderr,"%s: initialization failed\n",ng_dev.video_scan[i]);
-#endif
-			continue;
-		}
-
-		flags = driver->capabilities(handle);
-		if (flags & CAN_CAPTURE) {
-			GrabberDevice d;
-			d.device = ng_dev.video_scan[i];
-			if (driver->get_devname) {
-				d.name = driver->get_devname(handle);
-			}
-			d.type = driver->name;
-			devices.push_back(d);
-		}
-
-		driver->close(handle);
+	glob_t matches;
+	int globRv = glob("/dev/video*", 0, 0, &matches);
+	for (char** match = matches.gl_pathv; *match; ++match) {
+		GrabberDevice gd;
+		if (getGrabberDevice(*match, gd))
+			devices.push_back(gd);
 	}
-
+	globfree(&matches);
 	vector<GrabberDevice>(devices).swap(devices);
+	if (globRv == GLOB_NOSPACE)
+		throw std::bad_alloc();
 	return devices;
 }
 
--- stopmotion-0.8.0.orig/src/test/oomteststub.cpp
+++ stopmotion-0.8.0/src/test/oomteststub.cpp
@@ -26,12 +26,12 @@ namespace {
 typedef void setMallocsUntilFailure_t(int);
 typedef long mallocsSoFar_t(void);
 typedef void init_t(void);
-typedef void setMockFileSystem_t(MockableFileSystem*);
+typedef void wrapFileSystem_t(MockableFileSystem*);
 
 init_t* init;
 setMallocsUntilFailure_t* smuf;
 mallocsSoFar_t* msf;
-setMockFileSystem_t* smfs;
+wrapFileSystem_t* wfs;
 }
 
 MockableFileSystem::~MockableFileSystem() {
@@ -53,9 +53,9 @@ int loadOomTestUtil() {
 				"realSetMallocsUntilFailure");
 	if (!msf)
 		msf = (mallocsSoFar_t*)dlsym(RTLD_DEFAULT, "realMallocsSoFar");
-	if (!smfs)
-		smfs = (setMockFileSystem_t*)dlsym(RTLD_DEFAULT, "realSetMockFileSystem");
-	if (!init || !smuf || !msf || !smfs)
+	if (!wfs)
+		wfs = (wrapFileSystem_t*)dlsym(RTLD_DEFAULT, "realWrapFileSystem");
+	if (!init || !smuf || !msf || !wfs)
 		return 0;
 	init();
 	return 1;
@@ -77,7 +77,7 @@ long mallocsSoFar() {
 	return 0;
 }
 
-void setMockFileSystem(MockableFileSystem* mfs) {
-	if (smfs)
-		smfs(mfs);
+void wrapFileSystem(MockableFileSystem* mfs) {
+	if (wfs)
+		wfs(mfs);
 }
--- stopmotion-0.8.0.orig/src/test/oomtestutil.cpp
+++ stopmotion-0.8.0/src/test/oomtestutil.cpp
@@ -33,7 +33,7 @@ malloc_t malloc;
 void init();
 void realSetMallocsUntilFailure(int);
 long realMallocsSoFar();
-void realSetMockFileSystem(MockableFileSystem* mfs);
+void realWrapFileSystem(MockableFileSystem* mfs);
 FILE* fopen(const char* filename, const char* mode);
 FILE* freopen(const char* filename, const char* mode, FILE* fh);
 int fclose(FILE* fh);
@@ -215,9 +215,9 @@ long realMallocsSoFar() {
 	return mallocCount;
 }
 
-void realSetMockFileSystem(MockableFileSystem* mfs) {
+void realWrapFileSystem(MockableFileSystem* mfs) {
 	if (mfs) {
-		mfs->setDelegate(realFs);
+		mfs->setDelegate(requiredFs);
 		requiredFs = mfs;
 	} else {
 		requiredFs = realFs;
--- stopmotion-0.8.0.orig/src/test/oomtestutil.h
+++ stopmotion-0.8.0/src/test/oomtestutil.h
@@ -86,12 +86,13 @@ void cancelAnyMallocFailure();
 long mallocsSoFar();
 
 /**
- * Sets the mock file system object.
- * @param mfs The object to use as the mock file system. {@c setDelegate} will
- * be called on {@a mfs} with an object representing the real versions of these
- * functions which can be used as a delegate.
+ * Wraps the mock file system object.
+ * @param mfs The new object with which to wrap the file system.
+ * {@c setDelegate} will be called on {@a mfs} with an object representing the
+ * current versions of these functions which can be used as a delegate. If 0 is
+ * passed the file system will be returned to its natural unwrapped state.
  */
-void setMockFileSystem(MockableFileSystem* mfs);
+void wrapFileSystem(MockableFileSystem* mfs);
 
 }
 
--- stopmotion-0.8.0.orig/src/test/test.pro
+++ stopmotion-0.8.0/src/test/test.pro
@@ -28,11 +28,6 @@ HEADERS += ../domain/undo/filelogger.h \
     ../technical/audio/oggvorbis.h \
     ../technical/util.h \
     ../technical/stringiterator.h \
-    ../technical/libng/grab-ng.h \
-    ../technical/libng/struct-v4l.h \
-    ../technical/libng/struct-v4l2.h \
-    ../technical/libng/devices.h \
-    ../technical/libng/struct-dump.h \
     ../technical/video/videofactory.h \
     ../technical/video/videoencoder.h \
     ../technical/audio/ossdriver.h \
@@ -45,6 +40,7 @@ HEADERS += texecutor.h \
 	tcache.h \
     oomtestutil.h \
     testundo.h \
+    testhome.h \
     hash.h \
     tstopmotionundo.h
 SOURCES += ../domain/undo/filelogger.cpp \
@@ -74,13 +70,6 @@ SOURCES += ../domain/undo/filelogger.cpp
     ../technical/audio/audioformat.cpp \
     ../technical/util.cpp \
     ../technical/stringiterator.cpp \
-    ../technical/libng/grab-ng.c \
-    ../technical/libng/struct-v4l.c \
-    ../technical/libng/struct-v4l2.c \
-    ../technical/libng/plugins/drv0-v4l2.c \
-    ../technical/libng/plugins/drv1-v4l.c \
-    ../technical/libng/devices.c \
-    ../technical/libng/struct-dump.c \
     ../technical/video/videofactory.cpp \
     ../technical/video/videoencoder.cpp \
     ../technical/audio/ossdriver.cpp \
@@ -94,6 +83,7 @@ SOURCES += \
     texecutor.cpp \
     tcache.cpp \
     testundo.cpp \
+    testhome.cpp \
     hash.cpp \
     tstopmotionundo.cpp
 FORMS += 
--- /dev/null
+++ stopmotion-0.8.0/src/test/testhome.cpp
@@ -0,0 +1,114 @@
+/***************************************************************************
+ *   Copyright (C) 2014 by Linuxstopmotion contributors;                   *
+ *   see the AUTHORS file for details.                                     *
+ *                                                                         *
+ *   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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#include "testhome.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string>
+
+TestHome::TestHome() : delegate(0), fakeHome(0) {
+	std::string tmpdir("/tmp/t_home_lsmXXXXXX");
+	tmpdir.c_str(); // ensure trailing null is present
+	if (mkdtemp(&tmpdir[0])) {
+		std::string::size_type bufferSize = tmpdir.length() + 1;
+		fakeHome = (char *) malloc(bufferSize);
+		if (fakeHome) {
+			strncpy(fakeHome, tmpdir.c_str(), bufferSize);
+		} else {
+			printf("Could not create temporary directory: Out Of Memory!\n");
+		}
+	} else {
+		printf("Could not create temporary directory; error code: %d\n",
+				errno);
+	}
+}
+
+TestHome::~TestHome() {
+}
+
+void TestHome::setDelegate(MockableFileSystem* mfs) {
+	delegate = mfs;
+}
+
+FILE* TestHome::fopen(const char* filename, const char* mode) {
+	return delegate->fopen(filename, mode);
+}
+
+FILE* TestHome::freopen(const char* filename, const char* mode, FILE* fh) {
+	return delegate->freopen(filename, mode, fh);
+}
+
+int TestHome::fclose(FILE* fh) {
+	return delegate->fclose(fh);
+}
+
+int TestHome::fflush(FILE* fh) {
+	return delegate->fflush(fh);
+}
+
+size_t TestHome::fread (void *out, size_t blockSize,
+		     size_t blockCount, FILE *fh) {
+	return delegate->fread(out, blockSize, blockCount, fh);
+}
+
+size_t TestHome::fwrite (const void *in, size_t blockSize,
+		      size_t blockCount, FILE *fh) {
+	return delegate->fwrite(in, blockSize, blockCount, fh);
+}
+
+int TestHome::access (const char *name, int type) {
+	return delegate->access(name, type);
+}
+
+int TestHome::ferror(FILE* fh) {
+	return delegate->ferror(fh);
+}
+
+int TestHome::unlink(const char *name) {
+	return delegate->unlink(name);
+}
+
+int TestHome::ov_test(FILE *f, OggVorbis_File *vf, const char *initial, long ibytes) {
+	return delegate->ov_test(f, vf, initial, ibytes);
+}
+
+int TestHome::ov_clear(OggVorbis_File *vf) {
+	return delegate->ov_clear(vf);
+}
+
+int TestHome::ov_open(FILE *f, OggVorbis_File *vf, const char *initial, long ibytes) {
+	return delegate->ov_open(f, vf, initial, ibytes);
+}
+
+long TestHome::ov_read(OggVorbis_File *vf,char *buffer, int length, int bigendianp,
+		int word, int sgned, int *bitstream) {
+	return delegate->ov_read(vf, buffer, length, bigendianp, word, sgned,
+			bitstream);
+}
+
+char *TestHome::getenv(const char *name) {
+	if (0 == strcmp(name, "HOME")) {
+		return fakeHome;
+	}
+	return delegate->getenv(name);
+}
--- /dev/null
+++ stopmotion-0.8.0/src/test/testhome.h
@@ -0,0 +1,63 @@
+/***************************************************************************
+ *   Copyright (C) 2014 by Linuxstopmotion contributors;                   *
+ *   see the AUTHORS file for details.                                     *
+ *                                                                         *
+ *   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.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef TESTHOME_H_
+#define TESTHOME_H_
+
+#include "oomtestutil.h"
+
+struct OggVorbis_File;
+
+/**
+ * A filesystem/environment wrapper that makes only one change to the wrapped
+ * filesystem/environment: it creates a temporary directory and pretends that
+ * the HOME environment variable points to it.
+ * @par
+ * This is very useful for tests that exercise real Stopmotion functionality
+ * (that assumes the presence of HOME) because some automatic test runners do
+ * not have HOME set.
+ */
+class TestHome : public MockableFileSystem {
+	MockableFileSystem* delegate;
+	char* fakeHome;
+public:
+	TestHome();
+	~TestHome();
+	void setDelegate(MockableFileSystem* mfs);
+	FILE* fopen(const char* filename, const char* mode);
+	FILE* freopen(const char* filename, const char* mode, FILE* fh);
+	int fclose(FILE* fh);
+	int fflush(FILE* fh);
+	size_t fread (void *out, size_t blockSize,
+			     size_t blockCount, FILE *fh);
+	size_t fwrite (const void *in, size_t blockSize,
+			      size_t blockCount, FILE *fh);
+	int access (const char *name, int type);
+	int ferror(FILE* fh);
+	int unlink(const char *name);
+	int ov_test(FILE *f, OggVorbis_File *vf, const char *initial, long ibytes);
+	int ov_clear(OggVorbis_File *vf);
+	int ov_open(FILE *f, OggVorbis_File *vf, const char *initial, long ibytes);
+	long ov_read(OggVorbis_File *vf,char *buffer, int length, int bigendianp,
+			int word, int sgned, int *bitstream);
+	char *getenv(const char *name);
+};
+
+#endif
--- stopmotion-0.8.0.orig/src/test/testundo.cpp
+++ stopmotion-0.8.0/src/test/testundo.cpp
@@ -22,6 +22,8 @@
 
 #include "oomtestutil.h"
 
+#include "tstopmotionundo.h" // this will be moved.
+
 #include "src/domain/undo/executor.h"
 #include "src/domain/undo/commandlogger.h"
 #include "src/domain/undo/filelogger.h"
@@ -518,7 +520,7 @@ void testUndo(Executor& e, ModelTestHelp
 	ExecutorDoesAndRandomUndoesAndRedoes doesUndoesRedoes(&construct,
 			tmpFileName.c_str());
 
-	// (8) OOM[Do, undo some, redo some, do] = replay
+	// (8) OOM[Do, undo some, redo sometestundo, do] = replay
 	FailingStep failingDur(&doesUndoesRedoes);
 
 	const int commandCount = e.commandCount();
@@ -574,6 +576,11 @@ void testUndo(Executor& e, ModelTestHelp
 
 	QVERIFY2(0 == unlink(tmpFileName.c_str()), "Could not delete test command log file");
 	QVERIFY2(0 == rmdir(tmpDirName), "Could not delete test directory");
+	// The tests that rely on failing commands will pass if the fake malloc
+	// somehow does not cause any command to fail (this will happen, for
+	// example, if no allocations are actually made). If this happens too much
+	// then these tests are not being useful, so we check here that at least
+	// half of the tests run in each case did require recovering from a failure.
 	QVERIFY2(testCount / 2 < failToUndoThenRedo.failedCount()
 			|| testCount < failToUndoThenRedo.noMallocsCount(),
 			"failToUndoThenRedo didn't fail very often");
--- stopmotion-0.8.0.orig/src/test/texecutor.cpp
+++ stopmotion-0.8.0/src/test/texecutor.cpp
@@ -38,6 +38,7 @@
 
 #include "testundo.h"
 #include "oomtestutil.h"
+#include "testhome.h"
 
 static const int32_t no_num = std::numeric_limits<int32_t>::min();
 
--- stopmotion-0.8.0.orig/src/test/tstopmotionundo.cpp
+++ stopmotion-0.8.0/src/test/tstopmotionundo.cpp
@@ -21,6 +21,7 @@
 #include "tstopmotionundo.h"
 
 #include "testundo.h"
+#include "testhome.h"
 #include "oomtestutil.h"
 #include "hash.h"
 #include "src/domain/undo/addallcommands.h"
@@ -41,7 +42,6 @@
 #include <vector>
 #include <unistd.h>
 
-
 class RealOggEmptyJpg : public MockableFileSystem {
 	MockableFileSystem* delegate;
 	FILE* fake;
@@ -150,78 +150,6 @@ public:
 	}
 };
 
-class TestHome : public MockableFileSystem {
-	MockableFileSystem* delegate;
-	char* fakeHome;
-public:
-	TestHome() : delegate(0), fakeHome(0) {
-	}
-	~TestHome() {
-	}
-	void setDelegate(MockableFileSystem* mfs) {
-		delegate = mfs;
-		char* home = delegate->getenv("HOME");
-		if (home) {
-			static const char appendix[] = "/.stopmotion/test";
-			unsigned int len = strlen(home);
-			fakeHome = (char*) malloc(len + sizeof(appendix));
-			if (fakeHome) {
-				strncpy(fakeHome, home, len);
-				strncpy(fakeHome + len, appendix, sizeof(appendix));
-			}
-		}
-	}
-	FILE* fopen(const char* filename, const char* mode) {
-		return delegate->fopen(filename, mode);
-	}
-	FILE* freopen(const char* filename, const char* mode, FILE* fh) {
-		return delegate->freopen(filename, mode, fh);
-	}
-	int fclose(FILE* fh) {
-		return delegate->fclose(fh);
-	}
-	int fflush(FILE* fh) {
-		return delegate->fflush(fh);
-	}
-	size_t fread (void *out, size_t blockSize,
-			     size_t blockCount, FILE *fh) {
-		return delegate->fread(out, blockSize, blockCount, fh);
-	}
-	size_t fwrite (const void *in, size_t blockSize,
-			      size_t blockCount, FILE *fh) {
-		return delegate->fwrite(in, blockSize, blockCount, fh);
-	}
-	int access (const char *name, int type) {
-		return delegate->access(name, type);
-	}
-	int ferror(FILE* fh) {
-		return delegate->ferror(fh);
-	}
-	int unlink(const char *name) {
-		return delegate->unlink(name);
-	}
-	int ov_test(FILE *f, OggVorbis_File *vf, const char *initial, long ibytes) {
-		return delegate->ov_test(f, vf, initial, ibytes);
-	}
-	int ov_clear(OggVorbis_File *vf) {
-		return delegate->ov_clear(vf);
-	}
-	int ov_open(FILE *f, OggVorbis_File *vf, const char *initial, long ibytes) {
-		return delegate->ov_open(f, vf, initial, ibytes);
-	}
-	long ov_read(OggVorbis_File *vf,char *buffer, int length, int bigendianp,
-			int word, int sgned, int *bitstream) {
-		return delegate->ov_read(vf, buffer, length, bigendianp, word, sgned,
-				bitstream);
-	}
-	char *getenv(const char *name) {
-		if (0 == strcmp(name, "HOME")) {
-			return fakeHome;
-		}
-		return delegate->getenv(name);
-	}
-};
-
 void getHashes(std::vector<Hash>& out, const char* filenameTemplate) {
 	std::string filenameStr(filenameTemplate);
 	char* filename = &filenameStr[0];
@@ -278,7 +206,7 @@ TestStopmotionUndo::TestStopmotionUndo()
 }
 
 TestStopmotionUndo::~TestStopmotionUndo() {
-	setMockFileSystem(0);
+	wrapFileSystem(0);
 	delete mockFrontend;
 }
 
@@ -319,9 +247,11 @@ public:
 
 void TestStopmotionUndo::stopmotionCommandsInvertCorrectly() {
 	SceneVectorTestHelper helper(*sv);
-	setMockFileSystem(mfs);
+	wrapFileSystem(0);
+	wrapFileSystem(testEnvFs);
+	wrapFileSystem(mfs);
 	testUndo(*ex, helper);
-	setMockFileSystem(0);
+	wrapFileSystem(0);
 }
 
 class AnimTester {
@@ -438,7 +368,8 @@ public:
 };
 
 void TestStopmotionUndo::setUpAnim() {
-	setMockFileSystem(testEnvFs);
+	wrapFileSystem(0);
+	wrapFileSystem(testEnvFs);
 	WorkspaceFile::clear();
 	delete anim;
 	anim = 0;
--- stopmotion-0.8.0.orig/stopmotion.desktop
+++ stopmotion-0.8.0/stopmotion.desktop
@@ -2,7 +2,7 @@
 Name=Stopmotion
 Icon=stopmotion
 Comment=Program to create stop-motion animations
-Exec=stopmotion
+Exec=stopmotion %f
 Terminal=false
 Type=Application
 Categories=AudioVideo;Video;AudioVideoEditing;KDE;Qt;
--- stopmotion-0.8.0.orig/stopmotion.pro
+++ stopmotion-0.8.0/stopmotion.pro
@@ -1,5 +1,4 @@
 CONFIG += debug_and_release
-CONFIG += warn_off
 HEADERS += src/domain/undo/filelogger.h \
     src/config.h \
     src/domain/domainfacade.h \
@@ -112,14 +111,6 @@ HEADERS += src/domain/undo/filelogger.h
     src/application/externalcommand.h \
     src/application/externalcommandwithtemporarydirectory.h \
     src/presentation/frontends/qtfrontend/aboutdialog.h \
-    src/technical/libng/devices.h \
-    src/technical/libng/grab-ng.h \
-    src/technical/libng/list.h \
-    src/technical/libng/struct-dump.h \
-    src/technical/libng/struct-v4l2.h \
-    src/technical/libng/struct-v4l.h \
-    src/technical/libng/videodev2.h \
-    src/technical/libng/videodev.h \
     src/presentation/frontends/qtfrontend/devicetab.h \
     src/domain/undo/command.h \
     src/domain/undo/undoredoobserver.h \
@@ -194,13 +185,6 @@ SOURCES += src/config.cpp \
     src/application/externalcommand.cpp \
     src/application/externalcommandwithtemporarydirectory.cpp \
     src/presentation/frontends/qtfrontend/aboutdialog.cpp \
-    src/technical/libng/devices.c \
-    src/technical/libng/grab-ng.c \
-    src/technical/libng/struct-dump.c \
-    src/technical/libng/struct-v4l2.c \
-    src/technical/libng/struct-v4l.c \
-    src/technical/libng/plugins/drv0-v4l2.c \
-    src/technical/libng/plugins/drv1-v4l.c \
     src/presentation/frontends/qtfrontend/devicetab.cpp \
     src/domain/undo/command.cpp \
     src/domain/undo/undoredoobserver.cpp \
@@ -208,27 +192,7 @@ SOURCES += src/config.cpp \
     src/domain/undo/executor.cpp \
     src/domain/undo/addallcommands.cpp \
     src/domain/undo/random.cpp
-TRANSLATIONS += translations/stopmotion_no_nb.ts \
-                translations/stopmotion_no_nn.ts \
-                translations/stopmotion_no_se.ts \
-                translations/stopmotion_de.ts \
-                translations/stopmotion_sv.ts \
-                translations/stopmotion_fr.ts \
-                translations/stopmotion_br.ts \
-                translations/stopmotion_dk.ts \
-                translations/stopmotion_fi.ts \
-                translations/stopmotion_gr.ts \
-                translations/stopmotion_he.ts \
-                translations/stopmotion_ru.ts \
-                translations/stopmotion_es.ts \
-                translations/stopmotion_kl.ts \
-		translations/stopmotion_cz.ts \
-		translations/stopmotion_sl.ts \
-		translations/stopmotion_pt.ts \
-		translations/stopmotion_it.ts \
-		translations/stopmotion_tr.ts \
-		translations/stopmotion_zh_TW.ts \
-		translations/stopmotion_ar.ts
+TRANSLATIONS += $$system(ls -1 translations/*.ts)
 DEPENDPATH += src \
     src/domain \
     src/foundation \
@@ -246,6 +210,10 @@ INCLUDEPATH += . \
     src/presentation
 LIBS += -lSDL_image -ltar -lvorbisfile -lX11
 
+QM_FILES = $$TRANSLATIONS
+QM_FILES~= s:^translations/:build/:g
+QM_FILES~= s:[.]ts$:.qm:g
+
 DISTFILES += src/config.cpp.in \
     graphics/stopmotion.png \
     stopmotion.pro.in \
@@ -260,19 +228,20 @@ DISTFILES += src/config.cpp.in \
     $$system(ls -1 manual/graphic/*.png) \
     $$system(ls -1 manual/icons/*.png) \
     $$system(ls -1 manual/screenshots/*.png) \
-    $$system(ls -1 translations/*.ts | sed -e 's/translations\\(.*\\)\\.ts$/build\\1\\.qm/')
+    $$QM_FILES
 DISTFILES -= stopmotion.pro \
              src/config.cpp \
              stopmotion-d
 
 CONFIG += link_pkgconfig
 
+PKGCONFIG += sdl SDL_image vorbisfile libxml-2.0
+
 isEmpty(PREFIX) {
- PREFIX = /usr/local
+	PREFIX =/usr/local
 }
 
-PKGCONFIG += sdl SDL_image vorbisfile libxml-2.0
-DEFINES += PREFIX_PATH=\"\\\"$${PREFIX}\\\"\"
+DEFINES += PREFIX_PATH=\'\"$${PREFIX}\"\'
 TEMPLATE = app
 DESTDIR=.
 
@@ -292,13 +261,20 @@ UI_DIR = build
 target.path = $${PREFIX}/bin
 
 translations.path = $${PREFIX}/share/stopmotion/translations
-translations.files = build/*.qm
+translations.files = $${QM_FILES}
+translations.CONFIG += no_check_exist
+
+docgraphics.path = $${PREFIX}/share/doc/stopmotion/html/graphic
+docgraphics.files = manual/graphic/*.png
+
+docicons.path = $${PREFIX}/share/doc/stopmotion/html/icons
+docicons.files = manual/icons/*.png
+
+docscreens.path = $${PREFIX}/share/doc/stopmotion/html/screenshots
+docscreens.files = manual/screenshots/*.png
 
 htmldoc.path = $${PREFIX}/share/doc/stopmotion/html
 htmldoc.files = manual/*.html
-htmldoc.extra = $(INSTALL_DIR) manual/graphic $(INSTALL_ROOT)/$${PREFIX}/share/doc/stopmotion/html;
-htmldoc.extra += $(INSTALL_DIR) manual/icons $(INSTALL_ROOT)/$${PREFIX}/share/doc/stopmotion/html;
-htmldoc.extra += $(INSTALL_DIR) manual/screenshots $(INSTALL_ROOT)/$${PREFIX}/share/doc/stopmotion/html;
 
 icon.path = $${PREFIX}/share/icons
 icon.files = graphics/stopmotion.svg
@@ -306,24 +282,15 @@ icon.files = graphics/stopmotion.svg
 desktop.path = $${PREFIX}/share/applications
 desktop.files = stopmotion.desktop
 
-# Dummy target to fix permissions. 
-dummy.path = $${PREFIX}/bin
-dummy.extra += chmod 644 $(INSTALL_ROOT)/$${PREFIX}/share/stopmotion/translations/*.qm $(INSTALL_ROOT)/$${PREFIX}/share/doc/stopmotion/html/*.html \
-	$(INSTALL_ROOT)/$${PREFIX}/share/doc/stopmotion/html/graphic/* $(INSTALL_ROOT)/$${PREFIX}/share/doc/stopmotion/html/icons/* \
-    $(INSTALL_ROOT)/$${PREFIX}/share/doc/stopmotion/html/screenshots/*;
-dummy.extra += chmod 755 $(INSTALL_ROOT)/$${PREFIX}/share/stopmotion/translations $(INSTALL_ROOT)/$${PREFIX}/bin/$(QMAKE_TARGET) \
-	$(INSTALL_ROOT)/$${PREFIX}/share/doc/stopmotion/html $(INSTALL_ROOT)/$${PREFIX}/share/doc/stopmotion/html/graphic \
-    $(INSTALL_ROOT)/$${PREFIX}/share/doc/stopmotion/html/icons \
-	$(INSTALL_ROOT)/$${PREFIX}/share/doc/stopmotion/html/screenshots;
-
-INSTALLS += target translations htmldoc icon desktop dummy
+INSTALLS += target translations icon desktop \
+	docgraphics docicons docscreens htmldoc
 
 QMAKE_STRIP=:
 
 # Build translations
 QMAKE_EXTRA_COMPILERS += lrelease
 lrelease.input    = TRANSLATIONS
-lrelease.output   = ${QMAKE_FILE_BASE}.qm
+lrelease.output   = build/${QMAKE_FILE_BASE}.qm
 lrelease.commands = $$[QT_INSTALL_BINS]/lrelease ${QMAKE_FILE_IN} -qm build/${QMAKE_FILE_BASE}.qm
 lrelease.CONFIG  += no_link target_predeps
 
