/*****************************************************************************
 *
 *  player.cpp -- Audio/Video player class.
 *
 *  Copyright (C) 2010 Starbuck <starbuck@labdv.com>
 *  All rights reserved.
 *
 *  This file is part of the Player module of the DVDx 4 application.
 *
 *  GNU Lesser General Public License Usage
 *  This file may be used under the terms of the GNU Lesser General
 *  Public License version 2.1 as published by the Free Software
 *  Foundation and appearing in the file LICENSE.LGPL included in the
 *  packaging of this file.  Please review the following information to
 *  ensure the GNU Lesser General Public License version 2.1 requirements
 *  will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 *
 *  GNU General Public License Usage
 *  Alternatively, this file may be used under the terms of the GNU
 *  General Public License version 3.0 as published by the Free Software
 *  Foundation and appearing in the file LICENSE.GPL included in the
 *  packaging of this file.  Please review the following information to
 *  ensure the GNU General Public License version 3.0 requirements will be
 *  met: http://www.gnu.org/copyleft/gpl.html.
 *
 *****************************************************************************/

#include "player.h"
#include "interfacemplayer.h"
#include "../main/paths.h"
#include "../video/video_struct.h"
#include "../gui4/advancedmonitorwidget.h"
#include <QRegExp>
#include <QProcess>
#include <QCoreApplication>
#include <QDir>
#include <QDebug>

Player::Player(const int select,  const QString &binaryPath, 
			const QString &mediaInfoPath, const QString &ffprobePath,
			QTextEdit *stdIn, QTextEdit *stdOut, QTextEdit *stdErr,
			QTextEdit *defLog, const int verbosityLevel,
			const int latencyStart, const int latencyFinished, const int latencyKill)
{
	backend = select;
	binPath = binaryPath;
	mediaInfoBinPath = mediaInfoPath;
	ffprobeBinPath = ffprobePath;

	// Set IO channels from parent channels
	standardInput = stdIn;
	standardOutput = stdOut;
	standardError = stdErr;
	verbosity = verbosityLevel;
	log = defLog;
	
	LatencyStart = (latencyStart == 0) ? DefaultLatencyStart : latencyStart;
	LatencyFinished = (latencyFinished == 0) ? DefaultLatencyFinished : latencyFinished;
	LatencyKill = (latencyKill == 0) ? DefaultLatencyKill : latencyKill;

	capability = new player_engine_capability_t;

	capability->video = &videos; 
	capability->audio = &audios;

	status = new player_engine_status_t;

	mediaInfoData = new interfacemediainfo_data_t;
	mediaInfoStatus = new utility_status_t;

	ffprobeData = new interfaceffprobe_t;
	ffprobeStatus = new utility_status_t;

	initialize();
}

void Player::initialize()
{
	mediainfo = new InterfaceMediaInfo();
	mediainfo->initialize(mediaInfoBinPath, mediaInfoData, mediaInfoStatus);
	resetMediaInfo();

	ffprobe = new InterfaceFFprobe();
	ffprobe->initialize(ffprobeBinPath, ffprobeData, ffprobeStatus);
	resetFFprobe();

	switch (backend)
	{
	case 0:
		printErr(QObject::tr("player backend undefined"));
		break;
	case Video::Player::MPlayer:
		mplayer = new InterfaceMplayer();
		mplayer->initialize(binPath, capability, status);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	console = 0;
	targetWid.clear();
	resetBackend();
}

QString Player::engineVersion(const int engine)
{
	QString version;

	switch (engine)
	{
	case Video::Player::MPlayer:
		version = status->version;
		break;
	case Video::Player::VLC:
		version = QObject::tr("VLC not supported");
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	case Video::Player::MediaInfo:
		version = mediaInfoStatus->version;
		break;
	case Video::Player::FFprobe:
		version = ffprobeStatus->version;
		break;
	default:
		return "undefined";
	}

	return version; 
};

QString Player::getBinPath(const int engine)
{
	QString path;

	switch (engine)
	{
	case Video::Player::MPlayer:
		path = mplayer->getBinPath();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		path = QObject::tr("VLC not supported");
		break;
	case Video::Player::MediaInfo:
		path = mediainfo->getBinPath();
		break;
	case Video::Player::FFprobe:
		path = ffprobe->getBinPath();
		break;
	default:
		path = "undefined";
	}

	return path; 
}

void Player::resetMediaInfo()
{
	// Run test process to get signature and capabilities
	qDebug() << "Player: begin reset MediaInfo utitlity";
	printLog(QObject::tr("Player: MediaInfo utitlity reset begins."), VERBOSITY_VERBOSE);

	// Reset player status
	mediaInfoStatus->clear();

	// We don't use the player process member for this, we use a local QProcess
	QProcess process; // on the stack so no need to delete

	// Get player command line
	QString cmd;
	QStringList args;

	cliCmdGetMediaInfoStatus(&cmd, &args);

	// Player environment
#ifdef Q_OS_MAC

#elif defined(Q_OS_LINUX)
	// libmediainfo is in binary/../lib
	QDir dir( cmd );
	dir.cdUp();
	dir.cdUp();
	dir.cd( "lib" );
	QString mediainfoLibPath = dir.absolutePath();
	QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
	env.insert("LD_LIBRARY_PATH", mediainfoLibPath);
	process.setProcessEnvironment(env);
#endif

	// Run!
	QString strIn(cmd);
	strIn.append(" ").append(args.join(" "));
	printIn(strIn);

	qDebug() << "Player: start process" << cmd << args;
	printLog(QObject::tr("Player: MediaInfo process starts."), VERBOSITY_VERBOSE);

	process.start(cmd, args);

	if (!process.waitForStarted(LatencyStart))
	{
		qDebug() << "Player: MediaInfo process failed to start, waitForStarted() has timed out at (msec):"
			<< LatencyStart;
		printLog(QObject::tr("Player: MediaInfo process failed to start in %2 milliseconds.")
			.arg(LatencyStart), VERBOSITY_NORMAL);
		
		process.close();  // sounds safe to do this
		return;
	}

	qDebug("Player: MediaInfo process started.");
	printLog(QObject::tr("Player: MediaInfo process started."), VERBOSITY_VERBOSE);

	// Stop command not needed, process ends by itself but takes a few time (LatencyTest)
	if (!process.waitForFinished(LatencyFinished))
	{
		qDebug("Player: MediaInfo process didn't end by itself.");

		process.kill();

		qDebug("Player: kill MediaInfo process.");
		printLog( QObject::tr("Player: MediaInfo process being killed."), VERBOSITY_VERBOSE );

		if (!process.waitForFinished(LatencyKill))
		{
			qDebug("Warning: MediaInfo processs still running.");
			printLog( QObject::tr("Warning: MediaInfo process still running."), VERBOSITY_VERBOSE );
		}
		else
		{
			qDebug("Player: MediaInfo process killed.");
			printLog( QObject::tr("Player: MediaInfo process killed."), VERBOSITY_VERBOSE );
		}
	}
	
	// We can't use exitStatus() to ensure process ended normally because
	// return code is the count of analyzed files and -1 for --version
	if ( process.exitStatus() != QProcess::NormalExit &&  process.exitCode() != -1 )
	{
		qDebug("Warning: MediaInfo process crashed.");
		printLog( QObject::tr("Warning: MediaInfo process crashed."), VERBOSITY_NORMAL );
	}
	else
	{
		qDebug() << "Player: MediaInfo process finished.";
		printLog(QObject::tr("Player: MediaInfo process finished."), VERBOSITY_VERBOSE);
	}

	// Read output!
	mediaInfoStatus->cout = process.readAllStandardOutput();
	mediaInfoStatus->cerr = process.readAllStandardError();
	process.close();

	// Append outputs to standard IO
	printOut( mediaInfoStatus->cout );
	printErr( mediaInfoStatus->cerr );

	mediaInfoStatus->state = Video::Status::RawStatus;  // status cout/cerr are filled in

	// Parse raw data and we're done!
	mediainfo->parseStatus();

	printLog(QObject::tr("Player: MediaInfo utility reset completed."), VERBOSITY_VERBOSE);

	if ( mediaInfoStatus->state == Video::Status::EngineOk )
	{
		printLog(QObject::tr("Player: MediaInfo utility is ready."), VERBOSITY_VERBOSE);
	}
	else
	{
		printLog(QObject::tr("Player: MediaInfo utility binary is %2").arg(binPath), VERBOSITY_QUIET);
		printLog(QObject::tr("Player: MediaInfo utility failed initialization."), VERBOSITY_QUIET);
	}

	qDebug("Player: MediaInfo utility reset completed.");
}

void Player::readMediaInfo(const QString &path)
{
	// Run test process to get signature and capabilities
	qDebug() << "Player: begin read MediaInfo data";
	printLog(QObject::tr("Player: MediaInfo read data begins."), VERBOSITY_VERBOSE);

	// Reset player status
	mediaInfoData->clear();

	// We don't use the player process member for this, we use a local QProcess
	QProcess process; // on the stack so no need to delete

	// Get player command line
	QString cmd;
	QStringList args;

	cliCmdGetMediaInfoData(path, &cmd, &args);

#ifdef Q_OS_MAC

#elif defined(Q_OS_LINUX)
	// libmediainfo is in binary/../lib
	QDir dir( cmd );
	dir.cdUp();
	dir.cdUp();
	dir.cd( "lib" );
	QString mediainfoLibPath = dir.absolutePath();
	QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
	env.insert("LD_LIBRARY_PATH", mediainfoLibPath);
	process.setProcessEnvironment(env);
#endif

	// Run!
	qDebug() << "Player: start process" << cmd << args;
	printLog(QObject::tr("Player: MediaInfo process starts."), VERBOSITY_VERBOSE);

	process.start(cmd, args);

	if (!process.waitForStarted(LatencyStart))
	{
		qDebug() << "Player: MediaInfo process failed to start, waitForStarted() has timed out at (msec):"
			<< LatencyStart;
		printLog(QObject::tr("Player: MediaInfo process failed to start in %2 milliseconds.")
			.arg(LatencyStart), VERBOSITY_QUIET);
		
		process.close();  // sounds safe to do this
		return;
	}

	qDebug("Player: MediaInfo process started.");
	printLog(QObject::tr("Player: MediaInfo process started."), VERBOSITY_VERBOSE);

	// Stop command not needed, process ends by itself but takes a few time (LatencyTest)
	int latency(LatencyFinished);

	// MediaInfo can be very long on large files
	latency += 30000;  // so double wainting time

	if (!process.waitForFinished(latency))
	{
		qDebug("Player: MediaInfo process didn't end by itself.");

		process.kill();

		qDebug("Player: kill MediaInfo process.");
		printLog( QObject::tr("Player: MediaInfo process being killed."), VERBOSITY_VERBOSE );

		if (!process.waitForFinished(LatencyKill))
		{
			qDebug("Warning: MediaInfo processs still running.");
			printLog( QObject::tr("Warning: MediaInfo process still running."), VERBOSITY_VERBOSE );
		}
		else
		{
			qDebug("Player: MediaInfo process killed.");
			printLog( QObject::tr("Player: MediaInfo process killed."), VERBOSITY_VERBOSE );
		}
	}
	
	// We can't use exitStatus() to ensure process ended normally because
	// return code is the count of analyzed files and -1 for --version
	if ( process.exitStatus() != QProcess::NormalExit &&  process.exitCode() != 0 )
	{
		qDebug("Warning: MediaInfo process crashed.");
		printLog( QObject::tr("Warning: MediaInfo process crashed."), VERBOSITY_NORMAL );
	}
	else
	{
		qDebug() << "Player: MediaInfo process finished.";
		printLog(QObject::tr("Player: MediaInfo process finished."), VERBOSITY_VERBOSE);
	}

	// Read output!
	mediaInfoData->text = process.readAllStandardOutput();
	process.close();

	// Parse raw data and we're done!
	parseMediaInfoData( mediaInfoData );

	printLog(QObject::tr("Player: MediaInfo read data completed."), VERBOSITY_VERBOSE);

	qDebug("Player: read MediaInfo data completed.");
}

void Player::resetFFprobe()
{
	// Run test process to get signature
	qDebug() << "Player: begin reset FFprobe utitlity";
	printLog(QObject::tr("Player: FFprobe utitlity reset begins."), VERBOSITY_VERBOSE);

	// Reset status
	ffprobeStatus->clear();

	// We don't use the player process member for this, we use a local QProcess
	QProcess process; // on the stack so no need to delete

	// Get player command line
	QString cmd;
	QStringList args;

	cliCmdGetFFprobeStatus(&cmd, &args);

#ifdef Q_OS_MAC

#elif defined(Q_OS_LINUX)
	// ffprobe libs are in binary/../lib
	QDir dir( cmd );
	dir.cdUp();
	dir.cdUp();
	dir.cd( "lib" );
	QString ffprobeLibPath = dir.absolutePath();
	QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
	env.insert("LD_LIBRARY_PATH", ffprobeLibPath);
	process.setProcessEnvironment(env);
#endif

	// Run!
	QString strIn(cmd);
	strIn.append(" ").append(args.join(" "));
	printIn(strIn);

	qDebug() << "Player: start process" << cmd << args;
	printLog(QObject::tr("Player: FFprobe process starts."), VERBOSITY_VERBOSE);

	process.start(cmd, args);

	if (!process.waitForStarted(LatencyStart))
	{
		qDebug() << "Player: FFprobe process failed to start, waitForStarted() has timed out at (msec):"
			<< LatencyStart;
		printLog(QObject::tr("Player: FFprobe process failed to start in %2 milliseconds.")
			.arg(LatencyStart), VERBOSITY_NORMAL);
		
		process.close();  // sounds safe to do this
		return;
	}

	qDebug("Player: FFprobe process started.");
	printLog(QObject::tr("Player: FFprobe process started."), VERBOSITY_VERBOSE);

	// Stop command not needed, process ends by itself but takes a few time (LatencyTest)
	if (!process.waitForFinished(LatencyFinished))
	{
		qDebug("Player: FFprobe process didn't end by itself.");

		process.kill();

		qDebug("Player: kill FFprobe process.");
		printLog( QObject::tr("Player: FFprobe process being killed."), VERBOSITY_VERBOSE );

		if (!process.waitForFinished(LatencyKill))
		{
			qDebug("Warning: FFprobe processs still running.");
			printLog( QObject::tr("Warning: FFprobe process still running."), VERBOSITY_VERBOSE );
		}
		else
		{
			qDebug("Player: FFprobe process killed.");
			printLog( QObject::tr("Player: FFprobe process killed."), VERBOSITY_VERBOSE );
		}
	}
	
	// We can't use exitStatus() to ensure process ended normally because
	// return code is the count of analyzed files and -1 for --version
	if ( process.exitStatus() != QProcess::NormalExit &&  process.exitCode() != -1 )
	{
		qDebug("Warning: FFprobe process crashed.");
		printLog( QObject::tr("Warning: FFprobe process crashed."), VERBOSITY_NORMAL );
	}
	else
	{
		qDebug() << "Player: FFprobe process finished.";
		printLog(QObject::tr("Player: FFprobe process finished."), VERBOSITY_VERBOSE);
	}

	// Read output!
	QString cout = process.readAllStandardOutput();
	QString cerr = process.readAllStandardError();
	process.close();

	// Append outputs to standard IO
	printOut( cout );
	printErr( cerr );

	// Parse raw data and we're done!
	if ( ffprobe->parseStatus(&cout) )
	{
		printLog(QObject::tr("Player: FFprobe utility is ready."), VERBOSITY_VERBOSE);
	}
	else
	{
		printLog(QObject::tr("Player: FFprobe utility binary is %2").arg(binPath), VERBOSITY_QUIET);
		printLog(QObject::tr("Player: FFprobe utility failed initialization."), VERBOSITY_QUIET);
	}

	printLog(QObject::tr("Player: FFprobe utility reset completed."), VERBOSITY_VERBOSE);
	qDebug("Player: FFprobe utility reset completed.");
}

void Player::readFFprobe(const QString &path)
{
	// Run test process to get signature and capabilities
	qDebug() << "Player: begin read FFprobe data";
	printLog(QObject::tr("Player: FFprobe read data begins."), VERBOSITY_VERBOSE);

	// Reset player status
	ffprobeData->clear();

	// We don't use the player process member for this, we use a local QProcess
	QProcess process; // on the stack so no need to delete

	// Get player command line
	QString cmd;
	QStringList args;

	cliCmdGetFFprobeData(path, &cmd, &args);

	// Run!
	qDebug() << "Player: start process" << cmd << args;
	printLog(QObject::tr("Player: FFprobe process starts."), VERBOSITY_VERBOSE);

#ifdef Q_OS_MAC

#elif defined(Q_OS_LINUX)
	// ffprobe libs are in binary/../lib
	QDir dir( cmd );
	dir.cdUp();
	dir.cdUp();
	dir.cd( "lib" );
	QString ffprobeLibPath = dir.absolutePath();
	QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
	env.insert("LD_LIBRARY_PATH", ffprobeLibPath);
	process.setProcessEnvironment(env);
#endif

	process.start(cmd, args);

	if (!process.waitForStarted(LatencyStart))
	{
		qDebug() << "Player: FFprobe process failed to start, waitForStarted() has timed out at (msec):"
			<< LatencyStart;
		printLog(QObject::tr("Player: FFprobe process failed to start in %2 milliseconds.")
			.arg(LatencyStart), VERBOSITY_QUIET);
		
		process.close();  // sounds safe to do this
		return;
	}

	qDebug("Player: FFprobe process started.");
	printLog(QObject::tr("Player: FFprobe process started."), VERBOSITY_VERBOSE);

	// FFprobe can be very long on large file
	int latency = 10000;

	// Stop command not needed, process ends by itself but takes a few time (LatencyTest)
	if (!process.waitForFinished(latency))
	{
		qDebug("Player: FFprobe process didn't end by itself.");

		process.kill();

		qDebug("Player: kill FFprobe process.");
		printLog( QObject::tr("Player: FFprobe process being killed."), VERBOSITY_VERBOSE );

		if (!process.waitForFinished(LatencyKill))
		{
			qDebug("Warning: FFprobe processs still running.");
			printLog( QObject::tr("Warning: FFprobe process still running."), VERBOSITY_VERBOSE );
		}
		else
		{
			qDebug("Player: FFprobe process killed.");
			printLog( QObject::tr("Player: FFprobe process killed."), VERBOSITY_VERBOSE );
		}
	}
	
	// We can't use exitStatus() to ensure process ended normally because
	// return code is the count of analyzed files and -1 for --version
	if ( process.exitStatus() != QProcess::NormalExit &&  process.exitCode() != 0 )
	{
		qDebug("Warning: FFprobe process crashed.");
		printLog( QObject::tr("Warning: FFprobe process crashed."), VERBOSITY_NORMAL );
	}
	else
	{
		qDebug() << "Player: FFprobe process finished.";
		printLog(QObject::tr("Player: FFprobe process finished."), VERBOSITY_VERBOSE);
	}

	// Read output!
	QString stdOut = process.readAllStandardOutput();
	QString stdErr = process.readAllStandardError();
	process.close();

	qDebug() << stdOut;

	// Parse raw data and we're done!
	parseFFprobeData( ffprobeData, &stdOut,  &stdErr );

	printLog(QObject::tr("Player: FFprobe read data completed."), VERBOSITY_VERBOSE);

	qDebug("Player: read FFprobe data completed.");
}

void Player::resetBackend()
{
	// Run test process to get signature and capabilities
	qDebug() << "Player: begin reset backend type" << backend;
	printLog(QObject::tr("Player: %1 backend reset begins.").arg(name(backend)), VERBOSITY_VERBOSE);

	// Reset player status
	status->clear();

	// We don't use the player process member for this, we use a local QProcess
	QProcess process; // on the stack so no need to delete

	// Get player command line
	QString cmd;
	QStringList args;

	cliCmdGetStatus(&cmd, &args);

	// Run!
	QString strIn(cmd);
	strIn.append(" ").append(args.join(" "));
	printIn(strIn);

	qDebug() << "Player: start process" << cmd << args;
	printLog(QObject::tr("Player: %1 process starts.").arg(name(backend)), VERBOSITY_VERBOSE);

	process.start(cmd, args);

	if (!process.waitForStarted(LatencyStart))
	{
		qDebug() << "Player: process failed to start, waitForStarted() has timed out at (msec):"
			<< LatencyStart;
		printLog(QObject::tr("Player: %1 process failed to start in %2 milliseconds.")
			.arg(name(backend)).arg(LatencyStart), VERBOSITY_QUIET);
		
		process.close();  // sounds safe to do this
		return;
	}

	qDebug("Player: process started.");
	printLog(QObject::tr("Player: %1 process started.").arg(name(backend)), VERBOSITY_VERBOSE);

	// Stop command not needed, process ends by itself but takes a few time (LatencyTest)
	if (!process.waitForFinished(LatencyFinished))
	{
		qDebug("Player: process didn't end by itself.");

		process.kill();

		qDebug("Player: kill process.");
		printLog( QObject::tr("Player: %1 process being killed.").arg(name(backend)), VERBOSITY_VERBOSE );

		if (!process.waitForFinished(LatencyKill))
		{
			qDebug("Warning: player process still running.");
			printLog( QObject::tr("Warning: %1 process still running.").arg(name(backend)), VERBOSITY_VERBOSE );
		}
		else
		{
			qDebug("Player: process killed.");
			printLog( QObject::tr("Player: %1 process killed.").arg(name(backend)), VERBOSITY_VERBOSE );
		}
	}
		
	// Ensure process ended normally
	if ( process.exitStatus() == QProcess::CrashExit )
	{
		qDebug("Warning: player process crashed.");
		printLog( QObject::tr("Warning: %1 process crashed.").arg(name(backend)), VERBOSITY_NORMAL );
	}
	else
	{
		qDebug() << "Player: process finished.";
		printLog(QObject::tr("Player: %1 process finished.").arg(name(backend)), VERBOSITY_VERBOSE);
	}

	// Read output!
	status->cout = process.readAllStandardOutput();
	status->cerr = process.readAllStandardError();
	process.close();

	// Append outputs to standard IO
	printOut( status->cout );
	printErr( status->cerr );

	status->state = Video::Status::RawStatus;  // status cout/cerr are filled in

	// Parse raw data and we're done!
	parseStatus();

	printLog(QObject::tr("Player: %1 backend reset completed.").arg(name(backend)), VERBOSITY_VERBOSE);

	if ( status->state == Video::Status::EngineOk )
	{
		printLog(QObject::tr("Player: %1 backend is ready.").arg(name(backend)), VERBOSITY_VERBOSE);
	}
	else
	{
		printLog(QObject::tr("Player: %1 backend binary is %2").arg(name(backend)).arg(binPath), VERBOSITY_QUIET);
		printLog(QObject::tr("Player: %1 backend failed initialization.").arg(name(backend)), VERBOSITY_QUIET);
	}

	qDebug("Player: backend reset completed.");
}

void Player::setConsole(QTextEdit *widget)
{
	console = widget;	
}

void Player::setLatency(const int start, const int finished, const int kill)
{
	LatencyStart = start;
	LatencyFinished = finished;
	LatencyKill = kill;
}

void Player::setExternalRenderer(const int x, const int y, const int width)
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		mplayer->setExternalRenderer(x, y, width);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
}

void Player::setSize(const QSize s)
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		mplayer->setSize(s);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
}

void Player::setBinPath(const QString &path)
{
	binPath = path;

	// Prepare interface
	switch (backend)
	{
	case Video::Player::MPlayer:
		if (path.isNull())
		{
			printLog(QObject::tr("Player: %1 backend is disabled.").arg(name(backend)), VERBOSITY_NORMAL);
		}
		else
		{
			mplayer->setBinPath(path);
			resetBackend();
		}
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
}

void Player::setMediaInfoBinPath(const QString &path)
{
	mediaInfoBinPath = path;

	// Prepare interface
	if (path.isNull())
	{
		printLog(QObject::tr("Player: MediaInfo utility is disabled.").arg(name(backend)), VERBOSITY_NORMAL);
	}
	else
	{
		mediainfo->setBinPath(path);
		resetMediaInfo();
	}
}

void Player::setFFprobeBinPath(const QString &path)
{
	ffprobeBinPath = path;

	// Prepare interface
	if (path.isNull())
	{
		printLog(QObject::tr("Player: FFprobe utility is disabled.").arg(name(backend)), VERBOSITY_NORMAL);
	}
	else
	{
		ffprobe->setBinPath(path);
		resetFFprobe();
	}
}

void Player::setSoundOn()
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		mplayer->setSoundOn();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
}

void Player::setSoundOff()
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		mplayer->setSoundOff();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
}

void Player::setVideoOn()
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		mplayer->setVideoOn();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
}

void Player::setVideoOff()
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		mplayer->setVideoOff();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
}

void Player::setSubtitleOn()
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		mplayer->setSubtitleOn();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
}

void Player::setSubtitleOff()
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		mplayer->setSubtitleOff();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
}

void Player::setAudioId(const int &aid)
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		mplayer->setAudioLanguage(aid);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
}

void Player::setSubtitleId(const int &sid)
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		mplayer->setSubtitleLanguage(sid);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
}

void Player::setAngle(const int a)
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		mplayer->setAngle(a);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
}

void Player::setTitle(const int t)
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		mplayer->setTitle(t);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
}

void Player::setSliceCut(QList<slice_t> *slices)
{
	QList<int> chapters;

	switch (backend)
	{
	case Video::Player::MPlayer:
		printErr(QObject::tr("slices restricted as a chapter list in this implementation of InterfaceMplayer"));
		// Build a chapter list from slices
/*		for (int i = 0; i < slices->size(); ++i) 
		{
			chapters.append(slices[i].value.chapter);		
		}
*/
		chapters.append(4);
		chapters.append(1);
		chapters.append(2);
		mplayer->setChapterList(chapters);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
}

void Player::setSource(const QString &movie, const int type, const bool novideo)
{
	qDebug() << "Player: set source" << movie << "type" << type;

	source = movie;

	switch (backend)
	{
	case Video::Player::MPlayer:
		if (type == Video::Media::DVD)
			mplayer->setDvdSource(movie, 1);
		else
			mplayer->setFileSource(movie, novideo);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
}

void Player::setSource(const QString &movie, const int type, const int title)
{
	qDebug() << "Player: set source" << movie << "type" << type << "title" << title;

	source = movie;

	switch (backend)
	{
	case Video::Player::MPlayer:
		if (type == Video::Media::DVD)
			mplayer->setDvdSource(movie, title);
		else
			mplayer->setFileSource(movie);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
}

void Player::setWid(const QString &wid)
{
	qDebug() << "Player: set Wid" << wid;

	targetWid = wid;

	switch (backend)
	{
	case Video::Player::MPlayer:
		mplayer->setWid(targetWid);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
}

bool Player::setPreferredVideoDriver(const QString &driver)
{
	bool ok(false);

	switch (backend)
	{
	case Video::Player::MPlayer:
		ok = mplayer->setPreferredVideoDriver(driver);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return ok;
}

bool Player::soundOn()
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->soundOn();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return true;
}

bool Player::videoOn()
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->videoOn();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return true;
}

bool Player::subtitleOn()
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->subtitleOn();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return true;
}

QString Player::name(const int player)
{
	switch (player)
	{
	case Video::Player::MPlayer:
		return QString("MPlayer");
		break;
	case Video::Player::VLC:
		return QString("VLC");
		break;
	default:
		return QString("unknown");
	}
}

void Player::setVerbosity(const int verbose)
{
	verbosity = verbose;
}

void Player::printLog(const QString &message, const int verbosityLevel)
{
	if ( log == 0 )
		qDebug() << "Player Log:" << message;
	else if ( verbosityLevel <= verbosity )
		log->append( message );
}

void Player::printIn(const QString &message, const int verbosityLevel)
{
	if ( standardInput == 0)
		qDebug() << "Player stdIn:" << message;
	else if ( verbosityLevel <= verbosity )
		standardInput->append( message );
}

void Player::printOut(const QString &message, const int verbosityLevel)
{
	if ( standardOutput == 0)
		qDebug() << "Player stdOut:" << message;
	else if ( verbosityLevel <= verbosity )
		standardOutput->append( message );
}

void Player::printErr(const QString &message, const int verbosityLevel)
{
	if ( standardError == 0)
		qDebug() << "Player stdErr:" << message;
	else if ( verbosityLevel <= verbosity )
		standardError->append( message );
}

void Player::clearLog()
{
	if ( log != 0)
		log->clear();
}

void Player::clearIn()
{
	if ( standardInput != 0)
		standardInput->clear();
}

void Player::clearOut()
{
	if ( standardOutput != 0)
		standardOutput->clear();
}

void Player::clearErr()
{
	if ( standardError != 0)
		standardError->clear();
}

void Player::cliCmdIdentify(QString *cmd, QStringList *args)
{
	cmd->clear();
	args->clear();

	switch (backend)
	{
	case Video::Player::MPlayer:
		mplayer->cliCmdIdentify(cmd, args);
		return;
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return;
}

void Player::cliCmdUpdateFontCache(QString *cmd, QStringList *args)
{
	cmd->clear();
	args->clear();

	switch (backend)
	{
	case Video::Player::MPlayer:
		mplayer->cliCmdUpdateFontCache(cmd, args);
		return;
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return;
}

void Player::cliCmdPlay(QString *cmd, QStringList *args, int frames, int chapter, int seek, int volume)
{
	cmd->clear();
	args->clear();

	switch (backend)
	{
	case Video::Player::MPlayer:
		mplayer->cliCmdPlay(cmd, args, frames, chapter, seek, volume);
		return;
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return;
}

void Player::cliCmdGetStatus(QString *cmd, QStringList *args)
{
	cmd->clear();
	args->clear();

	switch (backend)
	{
	case Video::Player::MPlayer:
		mplayer->cliCmdGetStatus(cmd, args);
		return;
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		return;
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
}

QString Player::cliStop()
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliStop();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliSelectTitle(const int title)
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliSelectTitle(title);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliSelectAudio(const int audio)
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliSelectAudio(audio);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliSelectSubtitle(const int subtitle)
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliSelectSubtitle(subtitle);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliAvert(const QString &message, const int duration)
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliAvert(message, duration);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliShowProgress()
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliShowProgress();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliVideoResolution()
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliVideoResolution();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliTimeLength()
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliTimeLength();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliTimePosition()
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliTimePosition();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliChapter()
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliChapter();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliDeinterlace()
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliDeinterlace();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliSpeed()
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliSpeed();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliSeekChapter(const int chapt)
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliSeekChapter(chapt);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliSeekPrev(const int seconds)
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliSeekPrev(seconds);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliSeekNext(const int seconds)
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliSeekNext(seconds);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliSeekRelative(const int seconds)
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliSeekRelative(seconds);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliSeekPercent(const int percent)
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliSeekPercent(percent);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliSeek(const int seconds)
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliSeek(seconds);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliSetSpeedFaster()
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliSetSpeedFaster();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliSetSpeedSlower()
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliSetSpeedSlower();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliSetSpeedNormal()
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliSetSpeedNormal();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliSwitchAspectRatio(const double ratio)
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliSwitchAspectRatio(ratio);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliSwitchAngle(const int angle)
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliSwitchAngle(angle);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

QString Player::cliSwitchPause()
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->cliSwitchPause();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}

	return QString("");
}

bool Player::parseStdoutClip(const QByteArray &cout, int *state, video_clip_t *clip)
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->parseStdoutClip(cout, state, clip);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
	return false;
}

bool Player::parseStdoutDisk(const QByteArray &cout, int *state, mplayer_video_disk_t *disk)
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->parseStdoutDisk(cout, state, disk);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
	return false;
}

bool Player::parseStdoutRun(const QByteArray &cout, int *state, mplayer_video_running_t *run)
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		return mplayer->parseStdoutRun(cout, state, run);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
	return false;
}

void Player::parseStderr(const QByteArray &cerr, int *state, QString *message)
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		mplayer->parseStderr(cerr, state, message);
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
}

void Player::parseStatus()
{
	switch (backend)
	{
	case Video::Player::MPlayer:
		mplayer->parseStatus();
		break;
	case Video::Player::VLC:
		printErr(QObject::tr("player backend: VLC interface not implemented yet"));
		break;
	default:
		printErr(QObject::tr("player backend (type %1) unknown").arg(backend));
	}
}

void Player::cliCmdGetMediaInfoStatus(QString *cmd, QStringList *args)
{
	cmd->clear();
	args->clear();

	mediainfo->cliCmdGetStatus(cmd, args);
}

void Player::cliCmdGetMediaInfoData(const QString &path, QString *cmd, QStringList *args)
{
	cmd->clear();
	args->clear();

	mediainfo->cliCmdGetInfo(path, cmd, args);
}

void Player::parseMediaInfoData(interfacemediainfo_data_t *data)
{
	mediainfo->parseData(data);
}

void Player::cliCmdGetFFprobeStatus(QString *cmd, QStringList *args)
{
	cmd->clear();
	args->clear();

	ffprobe->cliCmdGetStatus(cmd, args);
}

void Player::cliCmdGetFFprobeData(const QString &path, QString *cmd, QStringList *args)
{
	cmd->clear();
	args->clear();

	ffprobe->cliCmdGetInfo(path, cmd, args);
}

void Player::parseFFprobeData(interfaceffprobe_t *data, QString *cout, QString *cerr)
{
	ffprobe->parseData(data, cout, cerr);
}

void Player::authenticateDvd(const QString &path)
{
	//*experimental: we try to authenticate the DVD by running dvdauth
#ifdef WIN32
	QString drive;
	QString dvdauth = "dvdauth.exe";
	QString authBin = QCoreApplication::applicationDirPath() + "/" + dvdauth;

	QRegExp rx("^([a-z]\\:).*");
	rx.setCaseSensitivity(Qt::CaseInsensitive);
	rx.setMinimal(false);
	if (rx.indexIn(path) == 0 && rx.numCaptures() == 1 && rx.cap(1).length() == 2)
	{
		drive = rx.cap(1);

		QString cmd;
		QStringList args;

		cmd = authBin.toLatin1();

		args << "-t" << QString::number(1);
		args << QString("-i%1").arg(drive);	

		QProcess process;

		qDebug() << "Start DVD authenticating process" << cmd << args;

		process.start(cmd, args);
	
		if (!process.waitForStarted(LatencyStart))
		{
			qDebug() << "Player: DVD authenticate process failed to start, waitForStarted() has timed out at (msec):"
				<< LatencyStart;

			printLog(tr("Player: DVD authenticate process (%1) failed to start in %2 milliseconds.")
				.arg(dvdauth).arg(LatencyStart), VERBOSITY_QUIET);
		
			process.close();  // sounds safe to do this
			return;
		}

		qDebug("Player: DVD authenticate process started.");
		printLog(tr("Player: DVD authenticate process (%1) started.").arg(dvdauth), VERBOSITY_VERBOSE);

		// Stop command not needed, process ends by itself but 
		// takes a few time (LatencyFinished) or crashes

		if (!process.waitForFinished(LatencyFinished))
		{
			qDebug("Player: DVD authenticate process didn't end by itself.");

			process.kill();

			qDebug("Player: kill DVD authenticate process.");
			printLog(tr("Player: DVD authenticate process (%1) being killed.").arg(dvdauth), VERBOSITY_QUIET);

			if (!process.waitForFinished(LatencyFinished))
			{
				qDebug("Warning: player DVD authenticate process still running.");
				printLog(tr("Player: DVD authenticate process (%1) still running.").arg(dvdauth), VERBOSITY_QUIET);
			}
			else
			{
				qDebug("Player: DVD authenticate process killed.");
				printLog(tr("Player: DVD authenticate process (%1) killed.").arg(dvdauth), VERBOSITY_QUIET);
			}
		}
		
		/*experimental: remove annoying crash warning (while dvdauth.exe terminates smoothly in command window)
		if ( process.exitStatus() == QProcess::CrashExit )
		{
			// Process returns dvdauth crash on Win32 but it succeeds at authenticate
			qDebug("Warning: player DVD authenticate process crashed.");
		}
		*/

		// Read output!
		printOut(process.readAllStandardOutput());
		printErr(process.readAllStandardError());

		process.close();

		printLog(tr("Player: DVD authenticate process (%1) done.").arg(dvdauth), VERBOSITY_VERBOSE);
	}
#endif

#ifdef Q_OS_LINUX
	QString dvdauth = "dvdauth";
	QString authBin = "/opt/dvdx4-open-edition/bin/" + dvdauth;

	// Is it a DVD drive?
	QProcess process;
	QStringList args;
	args << "-f" << path;
	process.start("stat", args);
	if (!process.waitForStarted(LatencyStart))
	{
		qDebug() << "Player: source type identification process failed to start, waitForStarted() has timed out at (msec):"
			<< LatencyStart;

		printLog(tr("Player: source type identification process (df -T %1) failed to start in %2 milliseconds.")
			.arg(path).arg(LatencyStart), VERBOSITY_QUIET);
	
		process.close();  // sounds safe to do this
		return;
	}
	if (!process.waitForFinished(LatencyFinished))
	{
		qDebug("Player: source type identification process didn't end by itself.");

		process.kill();

		qDebug("Player: kill DVD authenticate process.");
		printLog(tr("Player: source type identification process (df -T %1) being killed.").arg(path), VERBOSITY_QUIET);

		if (!process.waitForFinished(LatencyFinished))
		{
			qDebug("Warning: player source type identification process still running.");
			printLog(tr("Player: DVD authenticate process (df -T %1) still running.").arg(path), VERBOSITY_QUIET);
		}
		else
		{
			qDebug("Player: source type identification process killed.");
			printLog(tr("Player: source type identification process (df -T %1) killed.").arg(path), VERBOSITY_QUIET);
		}
	}
	QString cout, cerr;
	cout = process.readAllStandardOutput();
	cerr = process.readAllStandardError();
	printOut(cout);
	printErr(cerr);
	process.close();

	// UDF filesystem?
	if (cout.contains("Type: udf"))
	{
		QString cmd;
		QStringList args;

		cmd = authBin.toLatin1();

		args << "-t" << QString::number(1);
		args << QString("-i%1").arg(path);	

		QProcess process;

		qDebug() << "Start DVD authenticating process" << cmd << args;

		process.start(cmd, args);
	
		if (!process.waitForStarted(LatencyStart))
		{
			qDebug() << "Player: DVD authenticate process failed to start, waitForStarted() has timed out at (msec):"
				<< LatencyStart;

			printLog(tr("Player: DVD authenticate process (%1) failed to start in %2 milliseconds.")
				.arg(dvdauth).arg(LatencyStart), VERBOSITY_QUIET);
		
			process.close();  // sounds safe to do this
			return;
		}

		qDebug("Player: DVD authenticate process started.");
		printLog(tr("Player: DVD authenticate process (%1) started.").arg(dvdauth), VERBOSITY_VERBOSE);

		// Stop command not needed, process ends by itself but 
		// takes a few time (LatencyFinished) or crashes

		if (!process.waitForFinished(LatencyFinished))
		{
			qDebug("Player: DVD authenticate process didn't end by itself.");

			process.kill();

			qDebug("Player: kill DVD authenticate process.");
			printLog(tr("Player: DVD authenticate process (%1) being killed.").arg(dvdauth), VERBOSITY_QUIET);

			if (!process.waitForFinished(LatencyFinished))
			{
				qDebug("Warning: player DVD authenticate process still running.");
				printLog(tr("Player: DVD authenticate process (%1) still running.").arg(dvdauth), VERBOSITY_QUIET);
			}
			else
			{
				qDebug("Player: DVD authenticate process killed.");
				printLog(tr("Player: DVD authenticate process (%1) killed.").arg(dvdauth), VERBOSITY_QUIET);
			}
		}
		
		/*experimental: remove annoying crash warning (while dvdauth.exe terminates smoothly in command window)
		if ( process.exitStatus() == QProcess::CrashExit )
		{
			// Process returns dvdauth crash on Win32 but it succeeds at authenticate
			qDebug("Warning: player DVD authenticate process crashed.");
		}
		*/

		// Read output!
		printOut(process.readAllStandardOutput());
		printErr(process.readAllStandardError());

		process.close();

		printLog(tr("Player: DVD authenticate process (%1) done.").arg(dvdauth), VERBOSITY_VERBOSE);
	}
#endif

#ifdef Q_OS_MAC
	QString dvdauth = "dvdauth";
	QString authBin = "/opt/dvdx4/bin/" + dvdauth;

	// Is it a DVD drive?
	if (path.startsWith("/Volumes/"))
	{
		QString cmd;
		QStringList args;

		cmd = authBin.toLatin1();

		args << "-t" << QString::number(1);
		args << QString("-i%1").arg(path);	

		QProcess process;

		qDebug() << "Start DVD authenticating process" << cmd << args;

		process.start(cmd, args);
	
		if (!process.waitForStarted(LatencyStart))
		{
			qDebug() << "Player: DVD authenticate process failed to start, waitForStarted() has timed out at (msec):"
				<< LatencyStart;

			printLog(tr("Player: DVD authenticate process (%1) failed to start in %2 milliseconds.")
				.arg(dvdauth).arg(LatencyStart), VERBOSITY_QUIET);
		
			process.close();  // sounds safe to do this
			return;
		}

		qDebug("Player: DVD authenticate process started.");
		printLog(tr("Player: DVD authenticate process (%1) started.").arg(dvdauth), VERBOSITY_VERBOSE);

		// Stop command not needed, process ends by itself but 
		// takes a few time (LatencyFinished) or crashes

		if (!process.waitForFinished(LatencyFinished))
		{
			qDebug("Player: DVD authenticate process didn't end by itself.");

			process.kill();

			qDebug("Player: kill DVD authenticate process.");
			printLog(tr("Player: DVD authenticate process (%1) being killed.").arg(dvdauth), VERBOSITY_QUIET);

			if (!process.waitForFinished(LatencyFinished))
			{
				qDebug("Warning: player DVD authenticate process still running.");
				printLog(tr("Player: DVD authenticate process (%1) still running.").arg(dvdauth), VERBOSITY_QUIET);
			}
			else
			{
				qDebug("Player: DVD authenticate process killed.");
				printLog(tr("Player: DVD authenticate process (%1) killed.").arg(dvdauth), VERBOSITY_QUIET);
			}
		}
		
		/*experimental: remove annoying crash warning (while dvdauth.exe terminates smoothly in command window)
		if ( process.exitStatus() == QProcess::CrashExit )
		{
			// Process returns dvdauth crash on Win32 but it succeeds at authenticate
			qDebug("Warning: player DVD authenticate process crashed.");
		}
		*/

		// Read output!
		printOut(process.readAllStandardOutput());
		printErr(process.readAllStandardError());

		process.close();

		printLog(tr("Player: DVD authenticate process (%1) done.").arg(dvdauth), VERBOSITY_VERBOSE);
	}
#endif

	return;
}
