
/*
 * See the files COPYING and README for copyright information and how to reach 
 * the author.
 *
 *  $Id: process-dvd.c,v 1.4 2004/12/05 18:50:34 lordjaxom Exp $
 */

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

extern int DVDSIZE;

cBurnProcessDVD::cBurnProcessDVD(cBurnJob * Job):
cBurnProcess(__DVD_COUNT__)
{
    mJob = Job;
    mNumTracks = 0;
    mTrack = 0;
    mFactor = 0;
    mSizeMB = 0;
    mRender = new cBurnRender;

    mJob->SetTempDir(TempDir());
    SetLogfile("%s/dvd.log", TempDir());
    Start();
}

cBurnProcessDVD::~cBurnProcessDVD()
{
    delete mRender;
}

void cBurnProcessDVD::InitRepeat()
{
    cBurnProcess::InitRepeat();
    SetStep((int)sdGrowisofs);
}

void cBurnProcessDVD::Process(int Step, int SubStep, const char *Line)
{
    int done, total, temp;
    float fdone;
    char *asp;

    switch ((eStepDVD) Step) {
        case sdVdrsync:
            if (sscanf(Line, "%d Mbytes of %d read", &done, &total) == 2) {
                if (total > 0 && done <= total) {
                    SetProgress(mJob->Count(), done * 100 / total);
                }
            }
            break;

        case sdTcmplex:
            if (strn1cmp(Line, "*** Scanning video stream: 0%") == 0 ||
                    strn1cmp(Line, "*** Scanning audio stream: 0%") == 0 ||
                    strn1cmp(Line, "*** Multiplexing: 0%") == 0)
            {
                ++mTrack;
                SetProgress(mJob->Count(), mTrack, mNumTracks + 1, 0);
            } else if (sscanf(Line, "*** Scanning video stream: %d%%",
                        &done) == 1 ||
                    sscanf(Line, "*** Scanning audio stream: %d%%",
                        &done) == 1 ||
                    sscanf(Line, "*** Multiplexing: %d%%",
                        &done) == 1)
            {
                SetProgress(mJob->Count(), mTrack, mNumTracks + 1, done);
            }
            break;

        case sdDvdauthor:
            if (sscanf(Line, "STAT: fixing VOBU at %dMB (%d/%d, %d%%)", &temp,
                    &temp, &temp, &done) == 4)
            {
                SetProgress(mJob->Count(), done);
            }
            break;

        case sdGrowisofs:
            if (sscanf(Line, "%f%% done, estimate finish %as",
                    &fdone, &asp) == 2)
            {
                Dprintf("done: %f / %d \n", fdone, (int)fdone);
                SetBurning(true, (int)fdone);
                SetProgress(1, (int)fdone);
                free(asp);
            }
            break;

        default:
            break;
    }
}

bool cBurnProcessDVD::Continue(int Step, int SubStep)
{
    if (Step != sdGrowisofs && Status() == rsError) {
        return false;
    }

    switch ((eStepDVD)Step) {
        case sdVdrsync:
            if (SubStep < mJob->Count()) {
                cBurnRecording *rec = mJob->Get(SubStep);
                MakeDirectory("%s/VDRSYNC.%d", TempDir(), rec->Number());
                SetCmdline("%s SYNC '%s' %d '%s'",
                        Script, TempDir(), rec->Number(), rec->FileName());
            } else {
                SetNextStep();
            }
            break;

        case sdRequant:
            if (SubStep == 0) {
                mSizeMB += mJob->SizeMB();
                if (mSizeMB < DVDSIZE) {
                    SetNextStep();
                    break;
                } else {
                    mFactor = (mSizeMB * 1.04f) / DVDSIZE;
                }
            }

            if (SubStep > 0) {
                cBurnRecording *rec = mJob->Get(SubStep - 1);
                rec->RefreshTracks();
                const tTrackInfoArray & tracks = rec->GetTracks();
                if (!tracks.Size()) {
                    esyslog("BURN: No video tracks found");
                    SetStatus(rsError);
                    return false;
                }
            }

            if (SubStep < mJob->Count()) {
                double factor;
                double sizeMB;

                cBurnRecording *rec = mJob->Get(SubStep);
                const tTrackInfoArray & tracks = rec->GetTracks();

                if (!tracks.Size() || tracks[0]->Type() != ttVideo) {
                    esyslog("BURN: No video tracks found");
                    SetStatus(rsError);
                    return false;
                }

                sizeMB = FileSize(tracks[0]->Filename()) / 1024.f / 1024.f;
                factor = sizeMB / (sizeMB -
                        (rec->SizeMB(mJob->DiskType()) -
                        rec->SizeMB(mJob->DiskType()) / mFactor));
                setlocale(LC_ALL, "C");
                SetCmdline("%s REQUANT '%s' %d '%s' %.2f",
                        Script, TempDir(), rec->Number(),
                        tracks[0]->Filename(), factor);
                setlocale(LC_ALL, "");
            } else {
                SetNextStep();
            }
            break;

        case sdTcmplex:
            mTrack = -1;

            if (SubStep > 0) {
                cBurnRecording *rec = mJob->Get(SubStep - 1);
                Execute("nice -n 19 rm -rf %s/*.m[p2]v", rec->TempDir());
                Execute("nice -n 19 rm -rf %s/*.mp[a2]", rec->TempDir());
                Execute("nice -n 19 rm -rf %s/*.ac3", rec->TempDir());
            }

            if (SubStep < mJob->Count()) {
                cBurnRecording *rec = mJob->Get(SubStep);
                const tTrackInfoArray & tracks = rec->GetTracks();

                if (!tracks.Size() || tracks[0]->Type() != ttVideo) {
                    esyslog("BURN: No video tracks found");
                    SetStatus(rsError);
                    return false;
                }
                if (tracks[1]->Type() == ttUnknown) {
                    esyslog("BURN: No audio tracks found");
                    SetStatus(rsError);
                    return false;
                }
                mNumTracks = tracks.Size();

                SetCmdline("%s MPLEX '%s' '%s' '%s' '%s'",
                        Script, rec->TempDir(),
                        tracks[0]->Filename(),
                        tracks[1]->Filename(),
                        tracks[2] != NULL ? tracks[2]->Filename() : "");
            } else {
                SetNextStep();
            }
            break;

        case sdDvdmenu:
            if (SubStep < mJob->Count() && mJob->DiskType() == dtDVD) {
                cBurnRecording *rec = mJob->Get(SubStep);
                mRender->SetTitleMenu(rec);
                SetProcedure(cBurnRender::RenderProc, mRender);
            } else if (SubStep == mJob->Count() && mJob->DiskType() == dtDVD) {
                mRender->SetMainMenu(mJob);
                SetProcedure(cBurnRender::RenderProc, mRender);
            } else {
                SetNextStep();
            }
            break;

        case sdDvdauthor:
            if (SubStep == 0) {
                if (mJob->DiskType() == dtDVD) {
                    cDvdauthorConfig conf(mJob, "%s/dvd.xml", TempDir());
                    conf.SetTempDir(TempDir());
                    conf.Write();
                    MakeDirectory("%s/DVDAUTHOR", TempDir());
                    SetCmdline("%s AUTHOR '%s/dvd.xml'",
                            Script, TempDir());
                } else {
                    MakeDirectory("%s/DVDAUTHOR", TempDir());
                    SetCmdline("%s AUTHOR '%s'",
                            Script, TempDir());
                }
            } else {
                SetNextStep();
            }
            break;

        case sdGrowisofs:
            if (SubStep == 0) {
                char *path;

                switch (mJob->StoreMode()) {
                    case smAuthorOnly:
                        char *titlepath;
                        asprintf(&titlepath, "%s", mJob->Title());
                        SetCmdline("%s AUTHORONLY '%s' '%s' '%s'",
                                Script, TempDir(), ISOdir,
#if VDRVERSNUM >= 10333
                                ExchangeChars(titlepath, true));
#else
                                titlepath);
#endif
                        free(titlepath);
                        break;

                    case smCreateISO:
                        SetCmdline("%s MKISO '%s' '%s' '%s'",
                                Script, TempDir(), ISOdir, mJob->Title());
                        break;

                    case smBurnISO:
                        SetCmdline("%s BURN '%s' '%s' '%s'",
                                Script, TempDir(), DVDdev, mJob->Title());
                        break;

                    case smCreateBurn:
                        asprintf(&path, "%s/fifo", TempDir());
                        mkfifo(path, 0644);
                        SetCmdline("%s MKISO_BURN '%s' '%s' '%s' '%s' '%s'",
                                Script, TempDir(), DVDdev, ISOdir,
                                mJob->Title(), path);
                        free(path);
                        break;

                    default:
                        SetStatus(rsError);
                        return false;
                }
                SetBurning(true);
            } else if (Status() == rsError) {
                switch (mJob->StoreMode()) {
                    case smBurnISO:
                    case smCreateBurn:
                        Execute("eject %s", DVDdev);
                        cBurnMenuBurn::Confirm(
                                tr("Please insert an empty disk and press Ok"));
                        SetNextStep(nsRetry);
                        break;

                    default:
                        SetStatus(rsError);
                        return false;
                }
            } else {
                SetBurning(false);
                SetNextStep();
            }
            break;

        default:
            break;
    }
// Execute("svdrpsend.pl MESG %s", "DVD Erstellung abgeschlossen");
    return true;

}

double cBurnProcessDVD::SizeMB()
{
    return mSizeMB;
}
