/************************************************************************** * Copyright (C) 2005 by Jean-Michel Petit * * jm_petit@laposte.net * * * * 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., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "k9dvdauthor.h" #include "k9dvdtitle.h" #include "k9dvdbackup.h" #include "tdemessagebox.h" #include "k9tools.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class k9Progress; k9DVDAuthor::k9DVDAuthor(TQObject *DVDStruct,const char* name,const TQStringList& args) { DVD=(k9DVD*)DVDStruct; xml=NULL; cancelled=false; error=false; progress = new k9Progress(tqApp->mainWidget(),"progress",NULL); files.setAutoDelete(true); } k9DVDAuthor::~k9DVDAuthor() { TQPtrListIterator it (files); KTempFile *file; while ( (file = it.current()) != 0 ) { ++it; file->file()->remove(); } if (xml!=NULL) delete xml; } /** No descriptions */ void k9DVDAuthor::createXML() { int i; if (xml!=NULL) delete xml; xml=new TQDomDocument(); TQDomElement root = xml->createElement( "dvdauthor" ); root.setAttribute ("dest",workDir+"dvd"); xml->appendChild( root ); // Create vmgm menu TQDomElement vmgm = xml->createElement("vmgm"); root.appendChild(vmgm); addMenus(vmgm); m_totalPartSize=0; m_forced=0; m_forcedsh=0; uint64_t chapterssize=0; //computes the size of related titles for (int iTitle=0; iTitle < DVD->gettitleCount();iTitle++) { k9DVDTitle *title=DVD->gettitle(iTitle); if (title->isSelected() && title->getIndexed()) { chapterssize+= title->getChaptersSize(false); for (int iTitle2=0;iTitle2getTitles().count() ;iTitle2++) { k9DVDTitle *title2=title->getTitles().at(iTitle2); m_totalPartSize+= title2->getsize_mb() *1024*1024; if (title->getforceFactor()) { m_forced+=title2->getsectors()*2048; m_forcedsh+=(title2->getsectors()/title->getfactor())*2048; } chapterssize+= title2->getChaptersSize(false); } } //total size of forced titles if (title->isSelected() && title->getforceFactor()) { m_forced+=title->getsectors()*2048; m_forcedsh+=(title->getsectors()/title->getfactor())*2048; } } //total size of titles to copy m_totalSize=((uint64_t)DVD->getsizeSelected(false))*DVD_VIDEO_LB_LEN + m_totalPartSize -chapterssize*DVD_VIDEO_LB_LEN; m_firsttitle=true; for (i=0;i< DVD->gettitleCount();i++) { k9DVDTitle *tmp = DVD->gettitle(i); addTitle(root,tmp); } TQString x = xml->toString(); //TQFile file( locateLocal("tmp", "k9copy/k9author.xml" )); // if ( file.open( IO_WriteOnly ) ) { TQTextStream stream( m_xml->file() ); xml->save(stream,1); m_xml->file()->close(); // } } void k9DVDAuthor::addMenus(TQDomElement &titleSet) { int i; TQDomElement menu,video,pgc,pre,vob,button; TQDomText precmd; TQDomText buttonText; TQTime max(0,0); TQString c,start; k9DVDTitle * l_track= DVD->getstart(); if (l_track==NULL) { start="call vmgm menu;"; } else { if( DVD->getnewTitleNum(l_track)==-1) { error=true; TQString sMsg; //sMsg.TQString::sprintf(tr2i18n("'%s' not selected"),l_track->getname().latin1()); sMsg=i18n("'%1' not selected").arg(l_track->getname()); KMessageBox::error( 0,sMsg, tr2i18n("authoring")); } start.sprintf("jump titleset %d menu;",DVD->getnewTitleNum(l_track)); } factor=DVD->getfactor(false,false,true); menu=xml->createElement("menus"); titleSet.appendChild(menu); pgc=xml->createElement("pgc"); pgc.setAttribute("entry","title"); menu.appendChild(pgc); pre=xml->createElement("pre"); pgc.appendChild(pre); precmd=xml->createTextNode(""); TQString cmd="if (g0==0) \n { \n subtitle=0; \n g0=1;\n "+start+"\n}\n"; pre.appendChild(precmd); int numt=0; for (i=0;i < DVD->gettitleCount();i++) { if (DVD->gettitle(i)->isSelected() && DVD->gettitle(i)->getIndexed()) { ++numt; cmd+=c.sprintf("if (g1==%d) {jump titleset %d menu;}\n", numt,numt); } } precmd.setNodeValue(cmd); } /** No descriptions */ void k9DVDAuthor::addTitle(TQDomElement &root, k9DVDTitle *title) { int i,j; k9DVDSubtitle *l_sub; k9DVDAudioStream *l_auds; k9DVDTitle *l_track= title; TQDomElement e,t,pgc; TQString caud="",csub="",c,palette; if (l_track->isSelected() && l_track->getIndexed()) { double titleFactor; if (l_track->getforceFactor()) titleFactor=l_track->getfactor(); else titleFactor=factor; TQDomElement titleSet = xml->createElement("titleset"); root.appendChild(titleSet); TQDomElement titleMenu = xml->createElement("menus"); titleSet.appendChild(titleMenu); TQDomElement pgc = xml->createElement("pgc"); titleMenu.appendChild(pgc); TQDomElement pre = xml->createElement("pre"); pgc.appendChild(pre); TQDomText precmd=xml->createTextNode(""); int subtitle=0,audio=-1; if (l_track->getDefSubtitle() != NULL) { for (int isub=0;isubgetsubPictureCount();isub++) { if (l_track->getsubtitle(isub)->getselected()) { subtitle++; } if (l_track->getsubtitle(isub)==l_track->getDefSubtitle()) break; } } if (l_track->getDefAudio() != NULL) { for (int iaud=0;iaud < l_track->getaudioStreamCount();iaud++) { if (l_track->getaudioStream(iaud)->getselected()) { audio++; } if(l_track->getaudioStream(iaud)==l_track->getDefAudio()) break; } } TQString txtcmd; if (audio !=-1) { txtcmd="subtitle=%1;\n audio=%2;\n g1=0;jump title 1;"; txtcmd=txtcmd.arg(subtitle+63).arg(audio); } else { txtcmd="subtitle=%1;\n g1=0;jump title 1;"; txtcmd=txtcmd.arg(subtitle+63); } precmd.setNodeValue(txtcmd); pre.appendChild(precmd); //create palette for subpictures KTempFile *paletteFile=new KTempFile(locateLocal("tmp", "k9copy/k9p"), ".yuv"); files.append(paletteFile); paletteFile->setAutoDelete(false); palette=paletteFile->name(); //palette.sprintf("palette%d.yuv",l_track->getnumTitle()); //palette= locateLocal("tmp", "k9copy/k9" +palette); TQTextStream stream( paletteFile->file() ); for (j=0;j<16;j++) { l_track->getpalette(j,c); stream << c+"\n"; } paletteFile->file()->close(); t=xml->createElement("titles"); titleSet.appendChild(t); e=xml->createElement("video"); e.setAttribute("aspect",l_track->getaspectRatio()); e.setAttribute("format",l_track->getformat().lower()); if (l_track->getaspectRatio()!="4:3") { e.setAttribute("widescreen","nopanscan"); } t.appendChild(e); for (i=0;igetaudioStreamCount();i++) { l_auds=l_track->getaudioStream(i); if (l_auds->getselected()) { e=xml->createElement("audio"); e.setAttribute("format",l_auds->getformat()); e.setAttribute("channels",l_auds->getchannels()); e.setAttribute("quant",l_auds->getquantization()); e.setAttribute("lang",l_auds->getlangCod()); t.appendChild(e); if (caud != "") caud+=','; caud+=c.sprintf("%d",l_auds->getID()); } } for (i=0;igetsubPictureCount();i++) { l_sub=l_track->getsubtitle(i); if (l_sub->getselected()) { e=xml->createElement("subpicture"); e.setAttribute("lang",l_sub->getlangCod()); t.appendChild(e); if (csub !="") csub+=','; csub+=c.sprintf("%d",(l_sub->getID()).first()); } } pgc=xml->createElement("pgc"); pgc.setAttribute("palette",palette); t.appendChild(pgc); /* for (i=0;igetaudioStreamCount();i++) { l_auds=l_track->getaudioStream(i); if (l_auds->getselected()) { e=xml->createElement("audio"); e.setAttribute("id",l_auds->getID()-1); t.appendChild(e); if (caud != "") caud+=','; caud+=c.sprintf("%d",l_auds->getID()); } } for (i=0;igetsubPictureCount();i++) { l_sub=l_track->getsubtitle(i); if (l_sub->getselected()) { e=xml->createElement("subpicture"); e.setAttribute("id",(l_sub->getID()).first()-1); t.appendChild(e); if (csub !="") csub+=','; csub+=c.sprintf("%d",(l_sub->getID()).first()); } } */ if (caud !="") caud="--audiofilter "+caud; if (csub !="") csub="--subpicturefilter "+csub; int numPart=0; for (int iTitle=0;iTitle<=l_track->getTitles().count();iTitle++) { k9DVDTitle *title; if (iTitle==0) title=l_track; else title=l_track->getTitles().at(iTitle-1); for (i=0;igetchapterCount();i++) { numPart++; uint icell=0; k9DVDChapter *l_chap=title->getChapter(i); if (!l_chap->getSelected()) continue; bool first=true; uint32_t chapterSize= (l_chap->getendSector()-l_chap->getstartSector())*DVD_VIDEO_LB_LEN; TQString sChapter,sCell; for (k9ChapterCell *cell =l_chap->cells.first();cell ;cell =l_chap->cells.next() ) { icell++; sCell = TQString("--cell %1").arg(icell); sChapter=TQString("--chapter %1").arg(numPart); //test uint32_t itotSize = (cell->getlastSector()-cell->getstartSector())* DVD_VIDEO_LB_LEN; TQString file; e=xml->createElement("vob"); file=TQString("k9copy --play --input %1 --dvdtitle %2 %3 %4 %5 %6 --vampsfactor %7 --inputsize %8 --chaptersize %9 ") .arg(DVD->getDevice()) .arg(title->getnumTitle()) .arg(sChapter) .arg(sCell) .arg(caud) .arg(csub) .arg(titleFactor,0,'f',2) .arg(itotSize,0,'f',0) .arg(chapterSize,0,'f',0); if (m_firsttitle) { file +=" --initstatus "; m_firsttitle=false; } if (l_track->getforceFactor()) { file +=" --ffactor "; } file +=TQString(" --inject %1 --totalsize %2 --dvdsize %3 |") .arg(inject) .arg(m_totalSize -m_forced ,0,'f',0) .arg(((uint64_t)k9DVDSize::getMaxSize() *1024 *1024) - m_forcedsh,0,'f',0); e.setAttribute("file",file); if (first) e.setAttribute("chapters",l_chap->gettime().toString("0")); pgc.appendChild(e); first=false; } // } } } TQDomElement post = xml->createElement("post"); pgc.appendChild(post); TQDomText postcmd=xml->createTextNode(""); k9DVDTitle * l_next=l_track->getnextTitle(); if (l_next!=NULL) { c.sprintf("g1=%d;\ncall vmgm menu;",DVD->getnewTitleNum(l_next)); if( DVD->getnewTitleNum(l_next)==-1) { error=true; c=i18n("'%1' not selected").arg(l_next->getname()); KMessageBox::error( 0, c, tr2i18n("authoring")); } postcmd.setNodeValue(c); } post.appendChild(postcmd); } } const TQString& k9DVDAuthor::getworkDir() { return workDir; } void k9DVDAuthor::setworkDir( const TQString& _newVal) { workDir = _newVal; if (workDir.right(1)!='/') workDir +='/'; } void k9DVDAuthor::author() { if ( ! k9Tools::checkProgram("dvdauthor")) { KMessageBox::error (tqApp->mainWidget(),i18n("Unable to run %1").arg("dvdauthor") , i18n("authoring")); error = TRUE; return; } bool burnOk=false; //nettoyage du répertoire de sortie k9Tools::clearOutput(workDir+"dvd"); time = new TQTime(0,0); time->start(); progress->setTitle(i18n("Authoring")); progress->setCaption(i18n("k9Copy - Backup progression")); progress->setProgress(0,100); //progress->show(); m_xml=new KTempFile(locateLocal("tmp", "k9copy/k9a"),".xml"); m_inject=new KTempFile(locateLocal("tmp", "k9copy/k9v"),".inj"); inject=m_inject->name(); if (!cancelled && !error) createXML(); // if (error || cancelled) // delete progress; //run dvdauthor if (!cancelled && !error) { TQString c("dvdauthor"); proc=progress->getProcess();// new TQProcess(c,0); *proc << c << "-x" << m_xml->name(); //locateLocal("tmp", "k9copy/k9author.xml"); connect( proc, TQT_SIGNAL(receivedStderr(TDEProcess *, char *, int)), this, TQT_SLOT(DVDAuthorStderr(TDEProcess *, char *, int )) ); connect( proc, TQT_SIGNAL(receivedStdout(TDEProcess *, char *, int )), this, TQT_SLOT(DVDAuthorStdout(TDEProcess *, char *, int)) ); // connect(progress, TQT_SIGNAL(cancelled()), this, TQT_SLOT(stopProcess())); m_copied=0; m_lastPos=0; //if (m_totalSize >k9DVDSize::getMaxSize()) // m_totalSize=k9DVDSize::getMaxSize(); proc-> setWorkingDirectory(workDir); int result=progress->execute(); if ( result==-1 ) { KMessageBox::error( 0, tr2i18n("Dvdauthor error :\n") + lastMsg,tr2i18n("authoring")); } else { cancelled=(result==0); if ((proc->exitStatus()==0) && (proc->normalExit()) && !cancelled && !error) { burnOk=true; } else { if (cancelled) { //TQMessageBox::critical( 0, tr2i18n("authoring"), tr2i18n("Authoring canceled")); KMessageBox::error( 0, tr2i18n("Authoring cancelled"),tr2i18n("authoring")); } else KMessageBox::error( 0, tr2i18n("An error occured while running DVDAuthor:\n")+lastMsg ,tr2i18n("authoring")); } } // delete proc; // delete progress; if (!burnOk) error=true; } delete time; m_xml->file()->remove(); m_inject->file()->remove(); delete m_inject; delete m_xml; } /** No descriptions */ void k9DVDAuthor::DVDAuthorStderr(TDEProcess *proc, char *buffer, int buflen ) { //TQString m_stderr(proc->readStderr()); TQString m_stderr=TQString::fromLatin1(buffer, buflen); float m_percent; TQString m_remain; int pos=m_stderr.find("INFOPOS:"); if (pos!=-1) { progress->setTitle(i18n("Authoring")); TQString tmp=m_stderr.mid(pos); uint32_t totalBytes,totalSize; sscanf(tmp.latin1(),"INFOPOS: %d %d",&totalBytes,&totalSize); //if (totalBytes>m_lastPos) // m_copied+=totalBytes - m_lastPos; m_copied=totalBytes; m_lastPos=totalBytes; //tqDebug("%s", (TQString("copied : %1 totalSize : %2").arg(m_copied).arg(m_totalSize*512).ascii()); m_percent=(float)m_copied / (float)(m_totalSize/DVD_VIDEO_LB_LEN ); TQTime time2(0,0); time2=time2.addMSecs(time->elapsed()); if (m_percent>0) { TQTime time3(0,0); time3=time3.addMSecs((uint32_t)(time->elapsed()*(1/m_percent))); m_remain=time3.toString("hh:mm:ss"); } m_percent*=100; progress->setLabelText(""); progress->setProgress(m_percent,100); progress->setElapsed(time2.toString("hh:mm:ss") +" / " +m_remain); } /* else { if (!m_stderr.startsWith("libdvdread") && m_stderr.startsWith("libdvdnav")) tqDebug("%s", m_stderr.ascii()); } */ int end; lastMsg=m_stderr; if (m_stderr.contains("STAT:")) { pos=m_stderr.find("fixing VOBU"); if (pos!=-1) { progress->setTitle(i18n("Authoring")); progress->setLabelText(i18n("Fixing VOBUS")); end=m_stderr.find("%"); if (end!=-1) { pos =end -2; m_stderr=m_stderr.mid(pos,end-pos); m_stderr=m_stderr.stripWhiteSpace(); //progress->setLabelText(c); progress->setProgress(m_stderr.toInt(),100); } } } pos=m_stderr.find("INFOIMAGE:"); if (pos!=-1) { progress->setImage(m_stderr.mid(pos+10)); } } void k9DVDAuthor::DVDAuthorStdout(TDEProcess *proc, char *buffer, int buflen) { TQString c=TQString::fromLatin1( buffer,buflen); //(proc->readStdout()); int pos; pos=c.find("STAT"); if (pos!=-1) { c=c.mid(pos); progress->setLabelText(c); tqApp->processEvents(); } } /** No descriptions */ void k9DVDAuthor::stopProcess() { proc->kill(); cancelled=true; } /** Read property of bool burnDVD. */ const bool& k9DVDAuthor::getburnDVD() { return burnDVD; } /** Write property of bool burnDVD. */ void k9DVDAuthor::setburnDVD( const bool& _newVal) { burnDVD = _newVal; } bool k9DVDAuthor::getError() { return error; } #include "k9dvdauthor.moc"