/****************************************************************************
** Implementation of class MPlayerInfo
**
** Created: Tue Nov 23 07:53:05 2004
**      by: Varol Okan using the kate editor
**
** This class collects all possible information about
** the current set file.
**
****************************************************************************/

#include <unistd.h>
#include <stdlib.h>

#include <qprocess.h>
#include <qregexp.h>
#include <qimage.h>

#include "../../global.h"
#include "mplayerinfo.h"

MPlayerInfo::MPlayerInfo ()
	: QObject (), MediaInfo ()
{
	m_pSlaveProcess = NULL;
	m_qsTempPathName = QString ("%1/%2").arg(Global::qsTempPath).arg(Global::qsProjectName);
}

MPlayerInfo::MPlayerInfo  (void *pVoid)
	: QObject (), MediaInfo (pVoid)
{
	m_pSlaveProcess = NULL;
	m_qsTempPathName = QString ("%1/%2").arg(Global::qsTempPath).arg(Global::qsProjectName);
}

MPlayerInfo::~MPlayerInfo ()
{
	int iMaxCounter = 200;
	// Then we create a new slave process to obtain the length
	if (m_pSlaveProcess)	{
		while ((m_pSlaveProcess->isRunning()) && (iMaxCounter > 0))	{
			usleep (50000);	// = 50ms = 0.05 sec
			iMaxCounter --;
		}
		m_pSlaveProcess->kill();
		delete m_pSlaveProcess;
	}
}

void MPlayerInfo::queryValues ()
{
	QStringList listCommand;
	int iMaxCounter = 200;
	// Then we create a new slave process to obtain the length
	if (m_pSlaveProcess)	{
		while ((m_pSlaveProcess->isRunning()) && (iMaxCounter > 0))	{
			usleep (50000);	// = 50ms = 0.05 sec
			iMaxCounter --;
		}
 
		m_pSlaveProcess->kill();
		delete m_pSlaveProcess;
	}

	m_pSlaveProcess = new QProcess;

	listCommand.append(QString("mplayer"));
	listCommand.append(QString("-ao"));
	listCommand.append(QString("null"));
	listCommand.append(QString("-vo"));
	listCommand.append(QString("null"));
	listCommand.append(QString("-frames"));
	listCommand.append(QString("1"));

	listCommand.append(QString("-slave"));
	listCommand.append(QString("-identify"));
	listCommand.append(QString("--"));
	listCommand.append(QString("%1").arg(m_qsFileName));
	listCommand.append(QString("2>/dev/null"));

	connect (m_pSlaveProcess, SIGNAL(readyReadStdout()), this, SLOT (slotReadStdout ()));

	m_pSlaveProcess->clearArguments();
	m_pSlaveProcess->setArguments (listCommand);
	iMaxCounter = 200;
	if (m_pSlaveProcess->start())	{
		while ((m_pSlaveProcess->isRunning()) && (iMaxCounter > 0))	{
			usleep (50000);	// = 50ms = 0.05 sec
			iMaxCounter --;
		}
	}
}

void MPlayerInfo::slotReadStdout ()
{
//printf ("MPlayerInfo::slotReadStdout\n");
	QString qsWidth, qsHeight, qsWindowWidth, qsWindowHeight;
	QString qsLength, qsBuffer;
	QString qsStdout(m_pSlaveProcess->readStdout());
	if (qsStdout.length() == 0)
		return;
//printf ("    %s\n", (const char *)qsStdout);
	// Okay and here we process the received data.
	// VO: [xv] 352x240 => 352x264 Planar YV12
	QRegExp	regSize ("ID_VIDEO_WIDTH=([0-9]+)");
	if (regSize.search(qsStdout) > -1)	{
		qsWidth   = regSize.cap(1);
		m_iResolutionWidth  = qsWidth. toInt();
	}
	regSize = QRegExp ("ID_VIDEO_HEIGHT=([0-9]+)");
	if (regSize.search(qsStdout) > -1)	{
		qsHeight   = regSize.cap(1);
		m_iResolutionHeight = qsHeight.toInt();
	}
	// Here we precesso both values (if both are in ...
	if ( (m_iResolutionWidth > 0) && (m_iResolutionHeight > 0) )	{
		m_bVideoHandled = true;
		m_qsVideoFormat = getVideoFormat(m_iResolutionWidth, m_iResolutionHeight);
		m_qsResolution = QString ("%1x%2").arg(m_iResolutionWidth).arg(m_iResolutionHeight);
	}
	regSize = QRegExp ("ID_VIDEO_FPS=([0-9]+)");
	if (regSize.search(qsStdout) > -1)	{
		m_fFPS  = regSize.cap(1).toFloat();
		m_qsFPS = regSize.cap(1);
	}
	regSize = QRegExp ("ID_VIDEO_BITRATE=([0-9]+)");
	if (regSize.search(qsStdout) > -1)	{
		m_iVideoBPS  = regSize.cap(1).toInt();
		m_qsVideoBPS = regSize.cap(1);
	}
	regSize = QRegExp ("AO:.*");
	if (regSize.search(qsStdout) > -1)	{
		m_bAudioHandled = true;
	}
	// Movie-Aspect is 1.33:1 - prescaling to correct movie aspect.
	regSize = QRegExp ("Movie-Aspect is (\\S+).*");	//  1.33:1 OR undefined ...
	if (regSize.search(qsStdout) > -1)	{
		m_qsRatio = regSize.cap(1);
	}
	// Selected video codec: [mpeg12] vfm:libmpeg2 (MPEG 1 or 2 (libmpeg2))
	regSize = QRegExp ("ID_VIDEO_FORMAT=(\\S*)");
	if (regSize.searchRev(qsStdout) > -1)	{
		if (regSize.cap(1)[0] != '0')	// discard in case we get some cryptic 0x10000002 style of info ...
			m_qsVideoCodec = regSize.cap(1);
	}
	regSize = QRegExp ("Selected video codec:\\s*(\\S*)\\s*(\\S*).*");
	if (regSize.searchRev(qsStdout) > -1)	{
		if (m_qsVideoCodec.isEmpty())
			m_qsVideoCodec = regSize.cap(1) + QString (" ") + regSize.cap(2);
		m_bHasVideo = true;
		m_bVideoHandled = true;
	}
	// Selected audio codec: [mp3] afm:mp3lib (mp3lib MPEG layer-2, layer-3)
	regSize = QRegExp ("Selected audio codec:\\s*(\\S*)\\s*(\\S*).*");
	if (regSize.searchRev(qsStdout) > -1)	{
		m_bHasAudio = true;
		m_bAudioHandled = true;
	}
	// AUDIO: 44100 Hz, 2 ch, 16 bit (0x10), ratio: 28000->176400 (224.0 kbit)
	regSize = QRegExp ("ID_AUDIO_CODEC=(\\S*)");
	if (regSize.searchRev(qsStdout) > -1)	{
		m_qsAudioCodec = regSize.cap(1);
		m_bHasAudio = true;
	}
	regSize = QRegExp ("ID_AUDIO_BITRATE=(\\S*)");
	if (regSize.searchRev(qsStdout) > -1)	{
		m_qsAudioCodec = regSize.cap(1);
		m_bHasAudio = true;
	}
	regSize = QRegExp ("ID_AUDIO_BITRATE=([0-9]*)");
	if (regSize.searchRev(qsStdout) > -1)	{
		m_iAudioBPS  = regSize.cap(1).toInt();
		m_qsAudioBPS = regSize.cap(1);
		m_bHasAudio = true;
	}
	
	regSize = QRegExp ("ID_AUDIO_RATE=([0-9]*)");
	if (regSize.searchRev(qsStdout) > -1)	{
		m_iSample  = regSize.cap(1).toInt();
		m_qsSample = regSize.cap(1);
		m_bHasAudio = true;
	}
	regSize = QRegExp ("ID_AUDIO_NCH=([0-9]*)");
	if (regSize.searchRev(qsStdout) > -1)	{
		int iChannels = regSize.cap(1).toInt();
		m_qsAudioFormat = QString ("Undef.");
		if (iChannels == 2)
			m_qsAudioFormat = QString ("Stereo");
		else if (iChannels == 1)
			m_qsAudioFormat = QString ("Mono");
		m_bHasAudio = true;
	}
	regSize = QRegExp ("ID_AUDIO_BITRATE=([0-9]*)");
	if (regSize.searchRev(qsStdout) > -1)	{
		m_iAudioBPS  = regSize.cap(1).toInt();
		m_qsAudioBPS = regSize.cap(1);
		m_bHasAudio = true;
	}
	// AUDIO: 44100 Hz, 2 ch, 16 bit (0x10), ratio: 28000->176400 (224.0 kbit)
	regSize = QRegExp ("AUDIO:\\s*([0-9]+\\s*Hz),\\s([0-9]+\\s*ch),\\s([0-9]+\\s*bit).*([0-9\\.]+\\skbit).");
	if (regSize.searchRev(qsStdout) > -1)	{
		QString qsBits = regSize.cap(3);
		m_iBits        = qsBits.left(qsBits.length() - 4).toInt();
		m_bHasAudio = true;
	}
	// Das ist das absolut letzte !!!
	regSize = QRegExp ("ID_LENGTH=([0-9]*)");
	if (regSize.search(qsStdout) > -1)	{
		qsLength   = regSize.cap(1);
		m_iLength  = qsLength.toInt() * 1000;
		m_qsLength = QString ("00:00:00");

		float fTemp = qsLength.toFloat();
		if(fTemp != 0.0)	{
			int iHours, iMinutes, iSeconds;
			iHours  = (int)(fTemp/3600.0);
			fTemp    -= (iHours*3600.0);
			iMinutes= (int)(fTemp/60.0);
			fTemp    -= (iMinutes*60.0);
			iSeconds= (int)fTemp;
			m_qsLength.sprintf ("%02d:%02d:%02d", iHours, iMinutes, iSeconds);
		}
	}
	// Next we check the status of the media stream ...
	// Note: this info can be validated at any time ...
	if 	(   (m_bHasAudio && m_bAudioHandled) || 
		  ( (m_bHasVideo && m_bVideoHandled) && (m_iResolutionWidth > 0) && (m_iResolutionHeight) ) )
		m_qsStatus = QString ("Ok"); // E.g. Ok	-=> to say this file we can autmatically convert to a DVD video
//	test_print ();
}

QImage MPlayerInfo::getScreenshot( long iMSecOffset )
{
	// FIXME:
	// check out "-fixed-vo" "-aid" "-vid" "-sid" "-slang" options.
	// This function will generate screenshots and store them
	// under the defined <temp drive>/<BaseFileName>/00000001.jpeg
	// E.g. /tmp/movie/00000001.jpeg for ~/myMovies/movie.mpg
	QImage theImage;
	QString qsCommand, qsTempPath, m_qsScreenshotName;
	QTime timeOffset;
	timeOffset = timeOffset.addMSecs ( iMSecOffset );
	QFileInfo fileInfo(getFileName());

	qsTempPath = QString ("%1/%2").arg(m_qsTempPathName).arg(fileInfo.baseName());
	system ((const char *)QString("mkdir -p \"%1\"").arg(qsTempPath));
	
	m_qsScreenshotName  = QString ("%1/00000001.jpg").arg(qsTempPath);
	if (iMSecOffset != 0)	// For some reasons Mplayer produces always the first image from start
		m_qsScreenshotName  = QString ("%1/00000002.jpg").arg(qsTempPath);

	// Next we verify that the file has been created.
	fileInfo.setFile(m_qsScreenshotName);
	if (fileInfo.exists())
		system (QString("rm \"%1\"").arg(m_qsScreenshotName));
	
	// Here we generate the screenshot ...
//	qsCommand = QString("mplayer -ao null -vo jpeg:outdir=\"%1/\" -frames 2 -quiet \"%2\" &>/dev/null").arg(qsTempPath).arg(getFileName());
	if ( iMSecOffset == 0 )
		qsCommand = QString("mplayer -ao null -vo jpeg:outdir=\"%1/\" -frames 2 -quiet \"%2\" &>/dev/null").arg(qsTempPath).arg(getFileName());
	else
		qsCommand = QString("mplayer -ao null -vo jpeg:outdir=\"%1/\" -ss %2 -forceidx -frames 3 -quiet \"%3\" &>/dev/null").arg(qsTempPath).arg(timeOffset.toString()).arg(getFileName());

//printf ("MPlayerInfo::getScreenshot <%s>\n", (const char *)qsCommand);
	system (qsCommand);

	int iMaxWait = 0;
	while ((!fileInfo.exists()) && (iMaxWait < 4))	{
		sleep (1);
		iMaxWait ++;
	}
	if (fileInfo.exists())
		theImage = QImage (m_qsScreenshotName);
	return theImage;
}

bool MPlayerInfo::hasChapters ()
{
	return false;
}

/*  old version without the -identify - flag ...
void MPlayerInfo::slotReadStdout ()
{
printf ("MPlayerInfo::slotReadStdout\n");
	QString qsWidth, qsHeight, qsWindowWidth, qsWindowHeight;
	QString qsLength, qsBuffer;
	QString qsStdout(m_pSlaveProcess->readStdout());
	if (qsStdout.length() == 0)
		return;
printf ("    %s\n", (const char *)qsStdout);
	// Okay and here we process the received data.
	// VO: [xv] 352x240 => 352x264 Planar YV12
	QRegExp	regSize ("VO:.*[^0-9]([0-9]+)x([0-9]+)");
	if (regSize.search(qsStdout) > -1)	{
		qsWindowWidth   = regSize.cap(1);
		qsWindowHeight  = regSize.cap(2);
		m_bVideoHandled = true;
	}
	// VO: [xv] 352x240 => 352x264 Planar YV12
	regSize = QRegExp ("VO:[^0-9]+([0-9]+)x([0-9]+)");
	if (regSize.search(qsStdout) > -1)	{
		qsWidth   = regSize.cap(1);
		qsHeight  = regSize.cap(2);
		m_iResolutionWidth  = qsWidth. toInt();
		m_iResolutionHeight = qsHeight.toInt();
		m_qsResolution = QString (qsWidth+"x"+qsHeight);
		m_qsVideoFormat = getVideoFormat(m_iResolutionWidth, m_iResolutionHeight);
		m_bVideoHandled = true;
	}
	regSize = QRegExp ("AO:.*");
	if (regSize.search(qsStdout) > -1)	{
		m_bAudioHandled = true;
	}
	// Movie-Aspect is 1.33:1 - prescaling to correct movie aspect.
	regSize = QRegExp ("Movie-Aspect is (\\S+).*");	//  1.33:1 OR undefined ...
	if (regSize.search(qsStdout) > -1)	{
		m_qsRatio = regSize.cap(1);
	}
	// VIDEO:  [WMV2]  720x480  24bpp
	// VIDEO:  MPEG1  352x240  (aspect 12)  23.976 fps  1150.0 kbps (143.8 kbyte/s)
//	regSize = QRegExp ("VIDEO:.*([0-9\\.]+\\s*fps).*");	//  1.33:1 OR undefined ...
	regSize = QRegExp ("VIDEO:.*([0-9\\.]+\\s*fps)\\s*([0-9\\.]+\\s*kbps).*");
	if (regSize.search(qsStdout) > -1)	{
		m_qsFPS = regSize.cap(1);
		m_qsFPS = m_qsFPS.left(m_qsFPS.length()-4);
		m_fFPS  = m_qsFPS.toFloat();
		m_qsFPS = regSize.cap(1);
		m_qsVideoBPS = regSize.cap(2);
		m_iVideoBPS  = (int)m_qsVideoBPS.left(m_qsVideoBPS.length() - 5).toFloat();
	}
	// Selected video codec: [mpeg12] vfm:libmpeg2 (MPEG 1 or 2 (libmpeg2))
	regSize = QRegExp ("Selected video codec:\\s*(\\S*)\\s*(\\S*).*");
	if (regSize.searchRev(qsStdout) > -1)	{
		m_qsVideoCodec = regSize.cap(1) + QString (" ") + regSize.cap(2);
		m_bHasVideo = true;
		m_bVideoHandled = true;
	}
	// Selected audio codec: [mp3] afm:mp3lib (mp3lib MPEG layer-2, layer-3)
	regSize = QRegExp ("Selected audio codec:\\s*(\\S*)\\s*(\\S*).*");
	if (regSize.searchRev(qsStdout) > -1)	{
		m_qsAudioCodec = regSize.cap(1) + QString (" ") + regSize.cap(2);
		m_bHasAudio = true;
		m_bAudioHandled = true;
	}
	// AUDIO: 44100 Hz, 2 ch, 16 bit (0x10), ratio: 28000->176400 (224.0 kbit)
	regSize = QRegExp ("AUDIO:\\s*([0-9]+\\s*Hz),\\s([0-9]+\\s*ch),\\s([0-9]+\\s*bit).*([0-9\\.]+\\skbit).");
	if (regSize.searchRev(qsStdout) > -1)	{
		QString qsBits, qsChannels;
		int iChannels;
		m_qsSample     = regSize.cap(1);
		m_iSample      = m_qsSample.left(m_qsSample.length() - 3).toInt();
		qsChannels     = regSize.cap(2);
		iChannels      = qsChannels.left(qsChannels.length() - 3).toInt();
		m_qsAudioFormat = QString ("Undef.");
		if (iChannels == 2)
			m_qsAudioFormat = QString ("Stereo");
		else if (iChannels == 1)
			m_qsAudioFormat = QString ("Mono");
		qsBits         = regSize.cap(3);
		m_iBits        = qsBits.left(qsBits.length() - 4).toInt();
		m_qsAudioBPS   = regSize.cap(4);
		m_iAudioBPS    = (int)m_qsAudioBPS.left(m_qsAudioBPS.length() - 5).toFloat();
		m_bHasAudio = true;
	}
	// Das ist das absolut letzte !!!
	regSize = QRegExp ("ANS_LENGTH=([0-9]+)");
	if (regSize.search(qsStdout) > -1)	{
		qsLength   = regSize.cap(1);
		m_iLength = qsLength.toInt();
		m_qsLength = QString ("00:00:00");

		float fTemp = qsLength.toFloat();
		if(fTemp != 0.0)	{
			int iHours, iMinutes, iSeconds;
			iHours  = (int)(fTemp/3600.0);
			fTemp    -= (iHours*3600.0);
			iMinutes= (int)(fTemp/60.0);
			fTemp    -= (iMinutes*60.0);
			iSeconds= (int)fTemp;
			m_qsLength.sprintf ("%02d:%02d:%02d", iHours, iMinutes, iSeconds);
		}
		// Okay, this is the last info needed
		// Note that we have requested this info after all the other info is already in.
		m_pSlaveProcess->kill();
		delete m_pSlaveProcess;
		m_pSlaveProcess = NULL;
		// Next we check the status of the media stream ...
		if ( (m_bHasAudio && m_bAudioHandled) || (m_bHasVideo && m_bVideoHandled) )
			m_qsStatus = QString ("Ok"); // E.g. Ok	-=> to say this file we can autmatically convert to a DVD video
		// Finally we check out the values ...
//		getScreenshot(0);
//		test_print();
		return;
	}

	// We check for the string "Starting playback..."
	if (qsStdout.find ("Starting playback...\n") > -1)	{
		// We have to do some further processing.
		qsBuffer = QString ("get_time_length\n");
		m_pSlaveProcess->writeToStdin (qsBuffer);
	}
}
*/

