/*
 * See the files COPYING and README for copyright information and how to reach 
 * the author.
 *
 *  $Id: process-dvd.c,v 1.6 2006/03/12 17:53:31 lordjaxom Exp $
 */

#include "process-dvd.h"
#include "jobs.h"
#include "render.h"
#include "menuburn.h"
#include "config.h"
#include "setup.h"
#include "i18n.h"
#include <vdr/tools.h>
#include <vdr/interface.h>
#include <vdr/plugin.h>
#include <stdlib.h>

cBurnProcessDVD::cBurnProcessDVD(cBurnJob *Job):
		cBurnProcess(sd_Count),
		mJob(Job),
		mBuildStep(0),
		mFactor(1),
		mSizeMB(0)
{
	mJob->SetDirectories(TempDir(), DataDir());
	SetLogFile(mJob->GetLogFile());
	Start();
}

void cBurnProcessDVD::Process(int Step, int SubStep, const char *Line) 
{
	int done, temp;
	double fdone;
	char *str1, *str2;
	
	switch ((eStepDVD)Step) {
		case sdBuild:
			if (sscanf(Line, "STAT: Processing /%a[^/]/.vdr-burn.%a[^/]/"
					   "VDRSYNC.%d/movie.mpg...", &str1, &str2, &done) == 3) {
				int step;
				for (step = 0; step < mJob->Count(); ++step) {
					cBurnRecording *rec = mJob->Get(step);
					if (rec->Number() == done)
						break;
				}
				mBuildStep = step;
				printf("--- STEP: %d\n", step);
				free(str1);
				free(str2);
			} else if (sscanf(Line, "STAT: VOBU %d at %dMB, 1 PGCS", &temp, 
							  &done) == 2) {
				double size = 0;
				for (int i = 0; i < mBuildStep; ++i)
					size += mJob->Get(i)->SizeMB() / mFactor;
				size += done * .9f;
				SetProgress(1, (int)(size * 100.f / (mSizeMB / mFactor)));
			} else if (sscanf(Line, "STAT: fixing VOBU at %dMB (%d/%d, %d%%)", 
							  &done, &temp, &temp, &temp) == 4) {
				double size = 0;
				for (int i = 0; i < mBuildStep; ++i)
					size += mJob->Get(i)->SizeMB() / mFactor;
				size += mJob->Get(mBuildStep)->SizeMB() * .9f;
				size += done * .1f;
				SetProgress(1, (int)(size * 100.f / (mSizeMB / mFactor)));
			}
			break;

		case sdBurn:
			if (sscanf(Line, "%lf%% done, estimate finish ", &fdone) == 1) {
				SetBurning(true, (int)fdone);
				SetProgress(1, (int)fdone);
			}
			break;

		default:
			break;
	}
}

bool cBurnProcessDVD::Continue(int Step, int SubStep) 
{
	cBurnRecording *rec;

	if (Step != sdBurn && Status() == rsError)
		return false;

	switch ((eStepDVD)Step) {
		case sdBuild:
			if (SubStep == 0) {
				off64_t vsize = 0;
				off64_t asize = 0;
				
				for (rec = mJob->First(); rec != NULL; rec = mJob->Next(rec)) {
					mSizeMB += rec->SizeMB();
					vsize += rec->VideoTrack()->Size;
					for (int i = 0; i < MAXATRACKS && 
						 rec->AudioTrack(i)->Type != ttUnknown; ++i) {
						if (rec->AudioTrack(i)->Used)
							asize += rec->AudioTrack(i)->Size;
					}
				}

				if (vsize > (off64_t)mJob->DiskSize() * MEGABYTE(1) - asize)
					mFactor = (double)vsize / ((off64_t)mJob->DiskSize() * 
							  MEGABYTE(1) - asize) + .12;

				for (rec = mJob->First(); rec != NULL; rec = mJob->Next(rec)) {
					//XXX+ if (mVideoTrack.Type == ttUnknown)

					cString vFile        = rec->GetVideoTrack();
					cString aFiles       = rec->GetAudioTracks();
					cString ignoreTracks = rec->GetIgnoreTracks();
					cString movie        = rec->GetMovieFile();

					MakeDirectory(rec->TempDir());
					MakeDirectory(rec->DataDir());
					
					MakeFifo(vFile);
					MakeFifo(movie);

					for (int i = 0; i < MAXATRACKS; ++i) {
						tBurnTrackInfo *info = rec->AudioTrack(i);
						if (info->Type == ttUnknown) break;
						if (!info->Used) continue;

						MakeFifo(rec->GetAudioTrack(i));
					}

					if (mFactor > 1)
						PutEnvironment("REQUANT_FACTOR", mFactor);
					PutEnvironment("RECORDING_PATH", rec->FileName());
					PutEnvironment("VIDEO_FILE",     vFile);
					PutEnvironment("AUDIO_FILES",    aFiles);
					PutEnvironment("IGNORE_TRACKS",  ignoreTracks);
					PutEnvironment("MOVIE_FILE",     movie);
					PutEnvironment("MPEG_PATH",      rec->TempDir());

					AddCmdline("vdrburn-dvd.sh demux");
					AddCmdline("vdrburn-dvd.sh mplex");
				}

				printf("start render\n");
				if (!Execute(new cBurnRender(mJob))) { 
					// render gets deleted within Execute(...)
					SetStatus(rsError);
					return false;
				}
				printf("end render\n");
				
				cDvdauthorConfig conf(mJob);
				conf.Write();

				MakeDirectory(conf.GetAuthorPath());

				PutEnvironment("DVDAUTHOR_XML",  conf.GetXMLFile());
				PutEnvironment("DVDAUTHOR_PATH", conf.GetAuthorPath());
				PutEnvironment("ISO_FILE",       mJob->GetISOFile());
				PutEnvironment("DVD_DEVICE",     BurnParameters.DvdDevice);

				AddCmdline("vdrburn-dvd.sh author");
			} else
				SetNextStep();
			break;

		case sdBurn:
			if (SubStep == 0) {
				cString burnfifo = AddDirectory(TempDir(), "burnfifo");
				PutEnvironment("BURN_SPEED",     BurnSetup.BurnSpeed);

				switch (mJob->StoreMode()) {
					case smCreateISO:
						AddCmdline("vdrburn-dvd.sh mkiso");
						break;
			
					case smBurnISO:
						AddCmdline("vdrburn-dvd.sh burndir");
						break;

					case smCreateBurn:
						MakeFifo(burnfifo);

						PutEnvironment("ISO_PIPE", burnfifo);

						AddCmdline("vdrburn-dvd.sh pipeiso");
						AddCmdline("vdrburn-dvd.sh burniso");
						break;
				}
				SetBurning(true);
			} else if (Status() == rsError) {
				switch (mJob->StoreMode()) {
					case smBurnISO:
					case smCreateBurn:
						Execute("eject %s", BurnParameters.DvdDevice);
						cBurnMenuBurn::Confirm(tr("Please insert an empty disk and press Ok"));
						SetNextStep(nsRetry);
						break;

					default:
						SetStatus(rsError);
						return false;
				}
			} else {
				Execute("rm -rf %s/DVDAUTHOR", *DataDir());
				SetBurning(false);
				SetNextStep();
			}
			break;
			
		default:
			break;
	}
	return true;
}
