You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
k9copy/libk9copy/k9dvd.cpp

1097 lines
40 KiB

/**************************************************************************
* 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 "k9dvd.h"
#include "k9dvdtitle.h"
#include "k9dvdtitleset.h"
#include "k9cellcopylist.h"
#include "k9dvdprogress.h"
#include "k9ifo2.h"
#include <tqapplication.h>
#include <tdelocale.h>
#include <kdebug.h>
#include <sys/stat.h>
#include "k9dvd.moc"
k9DVDTitle* k9DVD::gettitle(int num) {
return ((k9DVDTitle*)m_titles.at(num));
}
k9DVDTitle* k9DVD::gettitleByNum(int num) {
int j=-1;
for (uint i=0; i < m_titles.count();i++) {
k9DVDTitle *track=(k9DVDTitle*)m_titles.at(i);
if (track->getIndexed()) {
j++;
if (j==num)
return track;
}
}
return (NULL);
}
/** Read property of int longestTitle. */
k9DVDTitle *k9DVD::getlongestTitle() {
return m_longestTitle;
}
/** Read property of TQString title. */
const TQString& k9DVD::getDVDTitle() {
return m_title;
}
void k9DVD::setDVDTitle(const TQString &_newVal) {
m_title=_newVal;
}
/** Read property of int titleCount. */
const int& k9DVD::gettitleCount() {
return m_titleCount;
}
/** Read property of int titlesetCount. */
const int& k9DVD::gettitlesetCount() {
return m_titlesetCount;
}
k9DVDTitleset *k9DVD::gettitleset(int num) {
return m_titlesets.at(num);
}
int k9DVD::getmenuSize() {
return m_menuSize;
}
k9DVD::k9DVD(TQObject *parent, const char *name,const TQStringList args) {
m_error=false;
m_opened=false;
m_titles.setAutoDelete(true);
m_titlesets.setAutoDelete(true);
m_lvideoFormat.append("NTSC");
m_lvideoFormat.append("PAL");
m_laspectRatio.append("4:3");
m_laspectRatio.append("16:9");
m_laspectRatio.append("?:?");
m_laspectRatio.append("16:9");
m_lquantization.append("16bps");
m_lquantization.append("20bps");
m_lquantization.append("24bps");
m_lquantization.append("drc");
m_lmpegVersion.append("mpeg1");
m_lmpegVersion.append("mpeg2");
m_lvideoHeight.append("480");
m_lvideoHeight.append("576");
m_lvideoHeight.append("???");
m_lvideoHeight.append("576");
m_lvideoWidth.append("720");
m_lvideoWidth.append("704");
m_lvideoWidth.append("352");
m_lvideoWidth.append("352");
m_lpermittedDf.append("");
m_lpermittedDf.append("noletterbox");
m_lpermittedDf.append("nopanscan");
m_lpermittedDf.append("noletterbox & nopanscan");
m_laudioFormat.append("ac3");
m_laudioFormat.append("?");
m_laudioFormat.append("mp2");
m_laudioFormat.append("mp2");
m_laudioFormat.append("pcm");
m_laudioFormat.append("sdds");
m_laudioFormat.append("dts");
m_lsampleFreq.append("48kHz");
m_lsampleFreq.append("48kHz");
m_laudioType.append("");
m_laudioType.append("Normal");
m_laudioType.append(i18n("for visually impaired"));
m_laudioType.append(i18n("director's comments"));
m_laudioType.append(i18n("alternate director's comments"));
m_lsubpType.append("");
m_lsubpType.append("Normal");
m_lsubpType.append(i18n("Large"));
m_lsubpType.append(i18n("Children"));
m_lsubpType.append(i18n("reserved"));
m_lsubpType.append(i18n("Normal captions"));
m_lsubpType.append(i18n("Large captions"));
m_lsubpType.append(i18n("Children captions"));
m_lsubpType.append("");
m_lsubpType.append(i18n("Forced"));
m_lsubpType.append(i18n("reserved"));
m_lsubpType.append(i18n("reserved"));
m_lsubpType.append(i18n("reserved"));
m_lsubpType.append(i18n("Director's comments"));
m_lsubpType.append(i18n("Large director's comments"));
m_lsubpType.append(i18n("Director's comments for children"));
m_frames_per_s[0]=-1.0;
m_frames_per_s[1]=25.00;
m_frames_per_s[2]=-1.0;
m_frames_per_s[3]=29.97;
m_start=NULL;
}
k9DVD::~k9DVD() {
if (m_dvd.opened())
m_dvd.close();
}
int k9DVD::dvdtime2msec(dvd_time_t *dt) {
double fps = m_frames_per_s[(dt->frame_u & 0xc0) >> 6];
long ms;
ms = (((dt->hour & 0xf0) >> 3) * 5 + (dt->hour & 0x0f)) * 3600000;
ms += (((dt->minute & 0xf0) >> 3) * 5 + (dt->minute & 0x0f)) * 60000;
ms += (((dt->second & 0xf0) >> 3) * 5 + (dt->second & 0x0f)) * 1000;
if(fps > 0)
ms +=(long)( ((dt->frame_u & 0x30) >> 3) * 5 + (dt->frame_u & 0x0f) * 1000.0 / fps);
return ms;
}
/*
* The following method is based on code from vobcopy, by Robos, with thanks.
*/
int k9DVD::get_title_name(const char* dvd_device, char* title) {
FILE *filehandle = 0;
int i;
TQString c;
if (! (filehandle = fopen(dvd_device, "r"))) {
c=i18n("Couldn't open %1 for title\n").arg(dvd_device);
// setError(c );
strcpy(title, i18n("unknown").latin1());
return -1;
}
if ( fseek(filehandle, 32808, SEEK_SET )) {
fclose(filehandle);
c=i18n("Couldn't seek in %1 for title\n").arg( dvd_device);
setError(c);
strcpy(title, i18n("unknown").latin1());
return -1;
}
if ( 32 != (i = fread(title, 1, 32, filehandle)) ) {
fclose(filehandle);
// c=tr2i18n("Couldn't read enough bytes for title.\n");
// setError(c);
strcpy(title, i18n("unknown").latin1());
return 0;
}
fclose (filehandle);
title[32] = '\0';
while(i-- > 2)
if(title[i] == ' ')
title[i] = '\0';
return 0;
}
TQString k9DVD::lang_name(const TQString& code,const TQString & name) {
TQString c;
int i=0;
lng arrLng[] = {
{ " ", i18n("Not Specified") }, { "aa", i18n("Afar") }, { "ab", i18n("Abkhazian") }, { "af", i18n("Afrikaans") }, { "am", i18n("Amharic")},
{ "ar", i18n("Arabic") }, { "as", i18n("Assamese") }, { "ay", i18n("Aymara") }, { "az", i18n("Azerbaijani") }, { "ba", i18n("Bashkir") },
{ "be", i18n("Byelorussian") }, { "bg", i18n("Bulgarian") }, { "bh", i18n("Bihari") }, { "bi", i18n("Bislama") }, { "bn", i18n("Bengali; Bangla") },
{ "bo", i18n("Tibetan") }, { "br", i18n("Breton") }, { "ca", i18n("Catalan") }, { "co", i18n("Corsican") }, { "cs", i18n("Czech") },
{ "cy", i18n("Welsh") }, { "da", i18n("Dansk") }, { "de", i18n("Deutsch") }, { "dz", i18n("Bhutani") }, { "el", i18n("Greek") }, { "en", i18n("English") },
{ "eo", i18n("Esperanto") }, { "es", i18n("Espanol") }, { "et", i18n("Estonian") }, { "eu", i18n("Basque") }, { "fa", i18n("Persian") },
{ "fi", i18n("Suomi") }, { "fj", i18n("Fiji") }, { "fo", i18n("Faroese") }, { "fr", i18n("Francais") }, { "fy", i18n("Frisian") }, { "ga", i18n("Gaelic") },
{ "gd", i18n("Scots Gaelic") }, { "gl", i18n("Galician") }, { "gn", i18n("Guarani") }, { "gu", i18n("Gujarati") }, { "ha", i18n("Hausa") },
{ "he", i18n("Hebrew") }, { "hi", i18n("Hindi") }, { "hr", i18n("Hrvatski") }, { "hu", i18n("Magyar") }, { "hy", i18n("Armenian") },
{ "ia", i18n("Interlingua") }, { "id", i18n("Indonesian") }, { "ie", i18n("Interlingue") }, { "ik", i18n("Inupiak") }, { "in", i18n("Indonesian") },
{ "is", i18n("Islenska") }, { "it", i18n("Italiano") }, { "iu", i18n("Inuktitut") }, { "iw", i18n("Hebrew") }, { "ja", i18n("Japanese") },
{ "ji", i18n("Yiddish") }, { "jw", i18n("Javanese") }, { "ka", i18n("Georgian") }, { "kk", i18n("Kazakh") }, { "kl", i18n("Greenlandic") },
{ "km", i18n("Cambodian") }, { "kn", i18n("Kannada") }, { "ko", i18n("Korean") }, { "ks", i18n("Kashmiri") }, { "ku", i18n("Kurdish") },
{ "ky", i18n("Kirghiz") }, { "la", i18n("Latin") }, { "ln", i18n("Lingala") }, { "lo", i18n("Laothian") }, { "lt", i18n("Lithuanian") },
{ "lv", i18n("Latvian, Lettish") }, { "mg", i18n("Malagasy") }, { "mi", i18n("Maori") }, { "mk", i18n("Macedonian") }, { "ml", i18n("Malayalam") },
{ "mn", i18n("Mongolian") }, { "mo", i18n("Moldavian") }, { "mr", i18n("Marathi") }, { "ms", i18n("Malay") }, { "mt", i18n("Maltese") },
{ "my", i18n("Burmese") }, { "na", i18n("Nauru") }, { "ne", i18n("Nepali") }, { "nl", i18n("Nederlands") }, { "no", i18n("Norsk") }, { "oc", i18n("Occitan") },
{ "om", i18n("Oromo") }, { "or", i18n("Oriya") }, { "pa", i18n("Punjabi") }, { "pl", i18n("Polish") }, { "ps", i18n("Pashto, Pushto") },
{ "pt", i18n("Portugues") }, { "qu", i18n("Quechua") }, { "rm", i18n("Rhaeto-Romance") }, { "rn", i18n("Kirundi") }, { "ro", i18n("Romanian") },
{ "ru", i18n("Russian") }, { "rw", i18n("Kinyarwanda") }, { "sa", i18n("Sanskrit") }, { "sd", i18n("Sindhi") }, { "sg", i18n("Sangho") },
{ "sh", i18n("Serbo-Croatian") }, { "si", i18n("Sinhalese") }, { "sk", i18n("Slovak") }, { "sl", i18n("Slovenian") }, { "sm",i18n( "Samoan") },
{ "sn", i18n("Shona") }, { "so", i18n("Somali") }, { "sq", i18n("Albanian") }, { "sr", i18n("Serbian") }, { "ss", i18n("Siswati") },
{ "st", i18n("Sesotho") }, { "su", i18n("Sundanese") }, { "sv", i18n("Svenska") }, { "sw", i18n("Swahili") }, { "ta", i18n("Tamil") },
{ "te", i18n("Telugu") }, { "tg", i18n("Tajik") }, { "th", i18n("Thai") }, { "ti", i18n("Tigrinya") }, { "tk", i18n("Turkmen") }, { "tl", i18n("Tagalog") },
{ "tn", i18n("Setswana") }, { "to", i18n("Tonga") }, { "tr", i18n("Turkish") }, { "ts", i18n("Tsonga") }, { "tt", i18n("Tatar") }, { "tw", i18n("Twi") },
{ "ug", i18n("Uighur") }, { "uk", i18n("Ukrainian") }, { "ur", i18n("Urdu") }, { "uz", i18n("Uzbek") }, { "vi", i18n("Vietnamese") },
{ "vo", i18n("Volapuk") }, { "wo", i18n("Wolof") }, { "xh", i18n("Xhosa") }, { "yi", i18n("Yiddish") }, { "yo", i18n("Yoruba") }, { "za", i18n("Zhuang") },
{ "zh", i18n("Chinese") }, { "zu", i18n("Zulu") }, { "xx", i18n("Unknown") }, { "\0", i18n("Unknown") } };
c=i18n("Unknown");
for (i=0 ; arrLng[i].code[0]!=0;i++) {
lng l =arrLng[i];
if (name=="") {
if (strcmp(code.latin1(),l.code)==0) {
c = l.name;
}
} else {
if (name == l.name) {
c = l.code;
}
}
}
return c;
}
int k9DVD::calcNumTitle(ifo_handle_t *ifo,int _vts,int _ttn) {
for (int i=0; i< ifo->tt_srpt->nr_of_srpts;i++) {
if (ifo->tt_srpt->title[i].title_set_nr==_vts && ifo->tt_srpt->title[i].vts_ttn == _ttn)
return (i+1);
}
return 0;
}
int k9DVD::scandvd (const TQString & device,bool _quickScan) {
char ctitle[255];
k9DVDChapter::setcptChapter(0);
ifo_handle_t *ifo_zero, *ifo;
pgcit_t *vts_pgcit;
vtsi_mat_t *vtsi_mat;
vmgi_mat_t *vmgi_mat;
audio_attr_t *audio_attr;
video_attr_t *video_attr;
subp_attr_t *subp_attr;
pgc_t *pgc;
int i, j, ltitles, cell, vts_ttn, title_set_nr;
char lang_code[3];
int has_title = 0;
int max_length = 0;
bool ok;
tt_srpt_t *tt_srpt;
TQString txt,c;
m_start=NULL;
int menuSizes[100];
for ( j=0; j<100;j++)
menuSizes[j]=0;
m_titles.clear();
m_Device=device;
m_error=false;
m_errMsg="";
if (!_quickScan) {
m_progressDlg= new k9DVDProgress(tqApp->mainWidget(),"progress",true);
m_progressDlg->setpbTitleStep(0);
m_progressDlg->setpbTotalStep(0);
connect(this, TQT_SIGNAL(sigVobProgress(unsigned int,unsigned int)), this, TQT_SLOT(slotVobProgress(unsigned int,unsigned int)));
connect(this, TQT_SIGNAL(sigTitleProgress(unsigned int,unsigned int)), this, TQT_SLOT(slotTitleProgress(unsigned int,unsigned int)));
connect(this, TQT_SIGNAL(sigTitleText(TQString&)), this, TQT_SLOT(slotTitleText(TQString&)));
connect(this, TQT_SIGNAL(sigTotalText(TQString&)), this, TQT_SLOT(slotTotalText(TQString&)));
m_progressDlg->show();
} else
m_progressDlg=NULL;
tqApp->processEvents();
k9DVDTitle *l_track;
k9DVDAudioStream *l_auds;
k9DVDChapter *l_chap;
k9DVDSubtitle *l_sub;
TQString sh,sm,ss;
/*
ret = stat(device.latin1(), &dvd_stat);
if ( ret < 0 ) {
c=i18n("Can't find device %1\n").arg( device);
setError(c);
return 1;
}
*/
if (m_dvd.opened())
m_dvd.close();
m_dvd.openDevice(device);
if( !m_dvd.opened() ) {
c=i18n("Can't open disc %1!\n").arg(device);
setError(c);
return 2;
}
// k9Ifo2 kifo_zero(&m_dvd),kifo(&m_dvd);
// kifo_zero.openIFO( 0);
k9Ifo2 *kifo_zero= m_dvd.getIfo(0);
k9Ifo2 *kifo;
ifo_zero = kifo_zero->getIFO();
if ( !ifo_zero ) {
c=tr2i18n("Can't open main ifo!\n");
setError(c);
return 3;
}
ltitles = ifo_zero->tt_srpt->nr_of_srpts;
m_titleCount = 0;
has_title = get_title_name(device.utf8(), ctitle);
vmgi_mat = ifo_zero->vmgi_mat;
m_titlesetCount = vmgi_mat->vmg_nr_of_title_sets;
menuSizes[0]=vmgi_mat->vmg_last_sector;
m_title=( has_title ? tr2i18n("unknown") : ctitle);
for (int ts=1;ts <=m_titlesetCount;ts++) {
tt_srpt = ifo_zero->tt_srpt;
kifo=m_dvd.getIfo(ts);
ifo = kifo->getIFO();
if (ifo==NULL)
continue;
//add the titleset in the titleset list
k9DVDTitleset *titleset = new k9DVDTitleset(ts,ifo->vtsi_mat->vts_last_sector -ifo->vtsi_mat->vtstt_vobs-1);
m_titlesets.append(titleset);
for (j=0; j < ifo->vts_pgcit->nr_of_pgci_srp; j++) {
// tt_srpt->title[j].title_set_nr);
// GENERAL
vtsi_mat = ifo->vtsi_mat;
vts_pgcit = ifo->vts_pgcit;
pgc = vts_pgcit->pgci_srp[j].pgc;
//retrieve the ttn
int ttn=(vts_pgcit->pgci_srp[j].entry_id) & 0x7F;
bool entryPgc= (vts_pgcit->pgci_srp[j].entry_id & 0x80)==0x80;
int numTitle=calcNumTitle(ifo_zero,ts,ttn);
//JMP : vérifier la numérotation des titres ......
if (vtsi_mat && (pgc->nr_of_cells >0)) {
m_titleCount++;
vts_ttn = ttn;//ifo->vts_ptt_srpt->title[j].ptt[0].pgcn; //ifo_zero->tt_srpt->title[j].vts_ttn;
//JMPtxt=i18n("Title %1").arg(indexedCount);
txt=i18n("Title %1").arg(numTitle);
emit sigTotalText (txt);
emit sigTitleProgress(numTitle,ltitles);
video_attr = &vtsi_mat->vts_video_attr;
vmgi_mat = ifo_zero->vmgi_mat;
title_set_nr = ts; //ifo_zero->tt_srpt->title[j].title_set_nr;
menuSizes[title_set_nr]=vtsi_mat->vtstt_vobs + vtsi_mat->vtsi_last_sector +1;
//vts_pgcit->pgci_srp[ifo->vts_ptt_srpt->title[vts_ttn - 1].ptt[0].pgcn - 1].pgc;
int titleStartSector=pgc->cell_playback[0].first_sector;
//l_track=addTitle(j+1,title_set_nr,ifo->vts_ptt_srpt->title[vts_ttn - 1].ptt[0].pgcn - 1,titleStartSector,isTitleIndex(ifo_zero,ts,vts_ttn));
l_track=addTitle(titleset,m_titleCount, numTitle,title_set_nr,j,titleStartSector, entryPgc);
titleset->add
(l_track);
sh.sprintf("%02x",pgc->playback_time.hour);
sm.sprintf("%02x",pgc->playback_time.minute);
ss.sprintf("%02x",pgc->playback_time.second);
l_track->length.setHMS(sh.toInt(&ok,10),sm.toInt(&ok,10),ss.toInt(&ok,10));
//printf(tr2i18n("Title: %02d, Length: %02x:%02x:%02x "), j+1, pgc->playback_time.hour, pgc->playback_time.minute, pgc->playback_time.second);
if (dvdtime2msec(&pgc->playback_time) > max_length && entryPgc) {
max_length = dvdtime2msec(&pgc->playback_time);
m_longestTitle = l_track;
}
l_track->chapterCount = pgc->nr_of_programs;// ifo_zero->tt_srpt->title[j].nr_of_ptts;
l_track->audioStreamCount = vtsi_mat->nr_of_vts_audio_streams;
l_track->subPictureCount = vtsi_mat->nr_of_vts_subp_streams;
l_track->VTS = ts;// ifo_zero->tt_srpt->title[j].title_set_nr;
l_track->TTN = ttn; // ifo_zero->tt_srpt->title[j].vts_ttn;
l_track->FPS = m_frames_per_s[(pgc->playback_time.frame_u & 0xc0) >> 6];
l_track->format= (*m_lvideoFormat.at(video_attr->video_format));
m_format = l_track->format;
/* TQStringList::Iterator it;
it= videoFormat.at(video_attr->video_format);
c= (*it).latin1();
*/
l_track->aspectRatio = (*m_laspectRatio.at(video_attr->display_aspect_ratio));
l_track->width = (*m_lvideoWidth.at(video_attr->picture_size));
;
l_track->height = (*m_lvideoHeight.at(video_attr->video_format));
l_track->DF = (*m_lpermittedDf.at(video_attr->permitted_df));
for (i=0; i<16; i++) {
TQString pal;
pal.sprintf("%08x",pgc->palette[i]);
l_track->palette.append(pal);
}
// ANGLES
l_track->angleCount = ifo_zero->tt_srpt->title[j].nr_of_angles;
// AUDIO
// for (i=0; i<vtsi_mat->nr_of_vts_audio_streams; i++) {
l_track->audioStreamCount=0;
for (i=0; i<vtsi_mat->nr_of_vts_audio_streams; i++) {
if (pgc->audio_control[i]>>8 !=0) {
l_track->audioStreamCount++;
l_auds=l_track->addAudioStream();
l_auds->id = 1+ ((pgc->audio_control[i]>>8) & 0x7) ;
//this only true for AC3 streams
l_auds->m_streamId = (pgc->audio_control[i]>>8);
audio_attr = &vtsi_mat->vts_audio_attr[i];
//dts stream starts at 0x88
if (audio_attr->audio_format==6)
l_auds->m_streamId +=8;
//JMPaudio_attr = &vtsi_mat->vts_audio_attr[l_auds->id-1];
snprintf(lang_code,3, "%c%c", audio_attr->lang_code>>8, audio_attr->lang_code & 0xff);
if (!lang_code[0]) {
lang_code[0] = 'x';
lang_code[1] = 'x';
}
l_auds->langCod=lang_code;
l_auds->language=lang_name(l_auds->langCod,"");
if (l_auds->language==i18n("Unknown"))
l_auds->langCod="xx";
l_auds->format= (*m_laudioFormat.at(audio_attr->audio_format));
l_auds->frequency = (*m_lsampleFreq.at(audio_attr->sample_frequency));
l_auds->quantization = (*m_lquantization.at(audio_attr->quantization));
l_auds->channels = audio_attr->channels+1;
l_auds->appMode = audio_attr->application_mode;
l_auds->content = (*m_laudioType.at(audio_attr->code_extension));
//if (((pgc->audio_control[i]>>8) & 0x80) ==0x80) {
//} else {
// l_auds->id=1;
//}
}
}
l_track->m_defAudio=NULL;
l_track->m_defSubtitle=NULL;
// CHAPTERS
cell = 0;
unsigned long total_sectors = 0;
l_track->chapterCount= pgc->nr_of_programs;
for (i=0;i < l_track->chapterCount;i++)
l_track->addChapter(i+1);
k9DVDChapter *l_pchap=NULL;
for (i=0; i<pgc->nr_of_programs; i++) {
int second=0, minute=0, hour=0, tmp;
char hex[3];
int next = pgc->program_map[i+1];
unsigned long sectors = 0;
l_chap = l_track->getChapter(i);
//first sector
l_chap->startSector=pgc->cell_playback[cell].first_sector;
;
l_chap->endSector=0;
if (i == pgc->nr_of_programs - 1)
next = pgc->nr_of_cells + 1;
int iangleStart=-1,iangleEnd=-1;
while (cell < next - 1) {
//using c2 otherwise the value of cell were lost
//int c2=cell;
//l_chap->cells.append(c2);
int startSect=pgc->cell_playback[cell].first_sector;
l_chap->startSectors.append(startSect);
snprintf(hex,3, "%02x", pgc->cell_playback[cell].playback_time.second);
tmp = second + atoi(hex);
minute = minute + (tmp / 60);
second = tmp % 60;
snprintf(hex,3, "%02x", pgc->cell_playback[cell].playback_time.minute);
tmp = minute + atoi(hex);
hour = hour + (tmp / 60);
minute = tmp % 60;
l_chap->endSector= pgc->cell_playback[cell].last_sector;
//last sector
/* Check if we're entering an angle block. (vamp_play-title) */
int cell2=cell;
if ( pgc->cell_playback[ cell ].block_type
== BLOCK_TYPE_ANGLE_BLOCK && cell>iangleEnd ) {
iangleStart=cell;
for( int idc = 0;; ++idc ) {
k9ChapterCell * chapterCell=new k9ChapterCell(cell2+idc,idc+1);
l_chap->cells.append(chapterCell);
chapterCell->setstartSector(pgc->cell_playback[cell2+idc].first_sector);
chapterCell->setlastSector(pgc->cell_playback[cell2+idc].last_sector);
if (idc==0)
chapterCell->setangleBlock(angleStart);
else
chapterCell->setangleBlock(angleInside);
if( pgc->cell_playback[ cell2 + idc ].block_mode
== BLOCK_MODE_LAST_CELL ) {
iangleEnd=cell2+idc;
chapterCell->setangleBlock(angleEnd);
sectors += pgc->cell_playback[iangleEnd].last_sector - pgc->cell_playback[iangleStart].first_sector + 1;
break;
}
}
} else {
if (!(cell>=iangleStart && cell <=iangleEnd)) {
k9ChapterCell * chapterCell=new k9ChapterCell(cell,1);
l_chap->cells.append(chapterCell);
chapterCell->setstartSector(pgc->cell_playback[cell].first_sector);
chapterCell->setlastSector(pgc->cell_playback[cell].last_sector);
sectors += pgc->cell_playback[cell].last_sector - pgc->cell_playback[cell].first_sector + 1;
}
}
cell++;
}
l_track->vobusize_mb += calcVobuSize(ifo,l_chap);
total_sectors += sectors;
l_chap->length.setHMS(hour,minute,second);
l_chap->sectors=sectors;
if (l_pchap!=NULL) {
TQTime t;
int position;
t.setHMS(0,0,0);
position=t.secsTo(l_chap->length);
t=l_pchap->time.addSecs(position);
l_chap->time=t;
}
l_pchap=l_chap;
}
l_track->size_mb =((float)total_sectors *2048)/(1024*1024);
l_track->m_sectors= total_sectors;
// SUBTITLES
l_track->subPictureCount=0;
for (i=0; i<vtsi_mat->nr_of_vts_subp_streams; i++) {
if (pgc->subp_control[i]>>24 !=0) {
l_sub=l_track->addSubtitle(i+1);
unsigned char subpc;
subpc=pgc->subp_control[i]>>24;
if ((subpc & 0x80)==0x80) {
if (l_track->aspectRatio=="4:3") {
l_sub->id.append(1+ (subpc & 0x1F));
} else {
subpc=(pgc->subp_control[i]>>16) & 0x1F;
l_sub->id.append(1+ subpc);
subpc=(pgc->subp_control[i]>>8) & 0x1F;
if (! l_sub->id.contains(1+ subpc) && ! l_track->DF.contains("noletterbox"))
l_sub->id.append(1+ subpc);
subpc=pgc->subp_control[i] & 0x1F;
if (! l_sub->id.contains(1+ subpc) && ! l_track->DF.contains("nopanscan"))
l_sub->id.append(1+ subpc);
}
kdDebug() << "VTS: " << l_track->VTS << " TTN: " << l_track->TTN << \
" Subtitle " << i+1 << ": " << l_sub->id << " " << l_sub->language << \
" " << l_sub->content << endl;
}
l_track->subPictureCount++;
subp_attr = &vtsi_mat->vts_subp_attr[i];
snprintf(lang_code,3, "%c%c", subp_attr->lang_code>>8, subp_attr->lang_code & 0xff);
if (!lang_code[0]) {
lang_code[0] = 'x';
lang_code[1] = 'x';
}
//JMP : l_sub->setselected(!titleIndexed);
l_sub->langCod=lang_code;
l_sub->language=lang_name(lang_code,"");
l_sub->content= (*m_lsubpType.at(subp_attr->code_extension));
}
}
if (entryPgc && !_quickScan)
calcStreamSize(*l_track);
}
}
//kifo.closeIFO();
}
m_menuSize=0;
for (j=0;j<100;j++)
m_menuSize+=menuSizes[j];
//kifo_zero.closeIFO();
if (!_quickScan)
delete m_progressDlg;
m_progressDlg=0;
m_opened=true;
//m_dvd.close();
return 0;
}
float k9DVD::calcVobuSize(ifo_handle_t *_ifo,k9DVDChapter *_chapter) {
vobu_admap_t * vobu_admap = _ifo->vts_vobu_admap;
int length = vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE;
float total=0;
for(uint32_t i = 0; i < length/sizeof(uint32_t); i++) {
if(vobu_admap->vobu_start_sectors[i] >= _chapter->startSector
&&vobu_admap->vobu_start_sectors[i] <= _chapter->endSector)
total++;
}
total=total*2048;
total=total/(1024*1024);
return total;
}
/** Adds a new track in the titles list the list is sorted by VTS and pgc*/
k9DVDTitle* k9DVD::addTitle(k9DVDTitleset *_titleset,int id,int num,int _VTS,int _pgc,uint32_t _startSector,bool _indexed) {
k9DVDTitle *track,*tmp;
track = new k9DVDTitle;
track->numTitle=num;
track->indexed=_indexed;
track->id=id;
track->m_titleset=_titleset;
//JMP : modification
track->forceSelection = false; // !_indexed;
track->ts_nr=_VTS;
track->pgc=_pgc;
bool bappend=true;
for (uint i=0;i<m_titles.count();i++) {
tmp=(k9DVDTitle*)m_titles.at(i);
k9DVDChapter *chap =tmp->getChapter(0);
if (tmp->ts_nr >_VTS) {
bappend=false;
} else if ( (tmp->ts_nr==_VTS) && ((tmp->pgc >_pgc) || (chap->getstartSector() > _startSector)) ) {
bappend=false;
}
if (!bappend) {
m_titles.insert(i,track);
break;
}
}
if (bappend)
m_titles.append(track);
track->name=i18n("Title %1").arg(num);
if (!_indexed) {
for (uint i=0;i<m_titles.count();i++) {
tmp=(k9DVDTitle*)m_titles.at(i);
if (tmp->numTitle==num && tmp->indexed)
tmp->m_titles.append(track);
}
}
return(track);
}
void k9DVD::calcStreamSize(k9DVDTitle & track) {
struct stream_counter streams[64];
int stream_count;
int start = 0;
int stop = 0;
k9DVDChapter *c_start,*c_stop;
struct streamSize streamList[64];
int c, x;
TQString pg;
for( x=0 ; x<64 ; x++ ) { // init stream usage list
streams[x].id = 0;
streams[x].count = 0;
streams[x].size_mb = 0;
streams[x].percent = 0;
streamList[x].id=0;
streamList[x].percent=0;
streamList[x].size_mb=0;
}
x = 0;
c = 0;
if( track.chapterCount == 2 ) { // select which chapters to probe for stream sizes
start=0;
stop=1;
}
if (track.chapterCount == 1) {
start=0;
stop=0;
}
if (track.chapterCount >2) {
start=0;
stop=(int)(track.chapterCount-1);
}
c_start=(k9DVDChapter*)track.chapters.at(start);
c_stop=(k9DVDChapter*)track.chapters.at(stop);
pg=tr2i18n("reading title");
emit sigTitleText(pg);
//probe stream usage
c = stream_vob( track.ts_nr,c_start->startSector, c_stop->endSector, streams);
for( x=0 ; x<64 ; x++ ) {
if( streams[x].id == 0 )
break;
streams[x].percent = (float)streams[x].count / (float)(c / 100.); // calc usage in percent
}
// create streamlist with all streams
stream_count=0;
for( c=0 ; c<64 ; c++ ) {
if( streams[c].id == 0 )
break;
streamList[stream_count].id = streams[c].id;
if( stream_count >= 64 )
break;
stream_count++;
x++;
}
// other_streams_mb = 0; // calc size of all selected streams
for( x=0 ; x<stream_count ; x++ ) {
for( c=0 ; c<64 ; c++ ) {
if( streamList[x].id == streams[c].id ) {
streamList[x].percent=streams[c].percent;
streamList[x].size_mb= (float) ((track.size_mb / 100.) * streams[c].percent);
}
}
}
k9DVDAudioStream *l_auds;
k9DVDSubtitle *l_sub;
k9DVDTitle *l_track;
int i;
l_track=&track;
for (x=0;x<64;x++) {
if (streamList[x].id==0)
break;
if (streamList[x].id== 0xe0)
l_track->videosize_mb = streamList[x].size_mb;
}
for (i=0;i<l_track->audioStreamCount;i++) {
l_auds=(k9DVDAudioStream*)l_track->audioStreams.at(i);
for (x=0;x<64;x++) {
if (streamList[x].id==0)
break;
int id=streamList[x].id;
if (( (id >=0x80) && (id <=0x8f)) || ((id >=0xa0) && (id <=0xa7)) || ((id >=0xc0) && (id <=0xdf))) {
if ( getVampsID(id) == l_auds->id) {
l_auds->size_mb = streamList[x].size_mb;
//stop the loop, go to next audio stream
break;
}
}
}
}
for (i=0;i<l_track->subPictureCount;i++) {
l_sub=(k9DVDSubtitle*)l_track->subtitles.at(i);
for (x=0;x<64;x++) {
if (streamList[x].id==0)
break;
int id=streamList[x].id;
if ( (id >=0x20) && (id <=0x3f)) {
if ( l_sub->id.contains(id - 0x20 +1) ) {
l_sub->size_mb = streamList[x].size_mb;
break;
}
}
}
}
}
int k9DVD::identify_stream( unsigned char *buffer ) {
uint8_t packet_type = buffer[17];
if( (packet_type >= 0xE0) && (packet_type <= 0xEF) ) { // video streams
;
} else if( packet_type == 0xBB ) { // system header
;
} else if( packet_type == 0xBE ) { // padding
;
} else if( packet_type == 0xBF ) { // nav pack
;
} else if( (packet_type >= 0xC0) && (packet_type <= 0xDF) ) { // mpeg audio
;
} else if( packet_type == 0xBD ) { // private stream, check content
packet_type = buffer[23+buffer[22]];
}
return packet_type;
}
long k9DVD::stream_vob( int title, unsigned long startblock, unsigned long lastblock, struct stream_counter *sc) {
k9DVDFile *dvdfile;
//JMP unsigned char buffer[DVD_VIDEO_LB_LEN];
unsigned char buffer[DVD_VIDEO_LB_LEN*800];
unsigned char *ptrbuff;
int blocksize=800,y;
int step=(int)((lastblock-startblock)/800) / 10;// * 0.05;
if (step==0)
step=1;
unsigned char stream_id;
long total=0;
unsigned long i, x ,nbread=0;
ssize_t size;
TQString c;
dvdfile =m_dvd.openTitle( title);
if( !dvdfile ) {
c=i18n("Error opening vobs for title %1\n").arg( title);
setError(c);
return 0;
}
i = startblock;
while( (i >= startblock) && (i <= lastblock) && (blocksize>0)) { // read blocks
size= dvdfile->readBlocks( i,blocksize , buffer);
emit sigVobProgress(i-startblock,lastblock-startblock);
total+=size;
if( !size ) {
c=i18n("ERROR reading block %1\n").arg(i);
setError(c);
break;
}
ptrbuff=buffer;
for (y=0;y<blocksize;y++) {
stream_id = identify_stream(ptrbuff); // get stream id
nbread++;
for( x=0 ; x<64 ; x++ ) { // scan for already present counter
if( sc[x].id != 0 ) {
if( stream_id != sc[x].id ) {
continue;
}
}
sc[x].id = stream_id; // increase stream packet counter
sc[x].count++;
break;
}
ptrbuff+=DVD_VIDEO_LB_LEN;
}
i+=blocksize*step;// 6;
if (i+blocksize> lastblock)
blocksize=lastblock-i;
}
dvdfile->close();
return total;
}
uint64_t k9DVD::getsizeSelected(bool _streams) {
uint64_t selstreams=0,vidstreams=0;
int i,x;
k9DVDTitle *l_track;
k9DVDAudioStream *l_auds;
k9DVDSubtitle *l_sub;
bool withvideo;
for (i=0;i<m_titleCount;i++) {
l_track=gettitle(i);
withvideo=l_track->isSelected() && l_track->getIndexed();
if ( withvideo) {
vidstreams +=l_track->getsectors();
if (_streams) {
for (x=0;x<l_track->audioStreamCount;x++) {
l_auds=l_track->getaudioStream(x);
if (!l_auds->selected)
selstreams += l_auds->size_mb*512;
}
for (x=0;x<l_track->subPictureCount;x++) {
l_sub=l_track->getsubtitle(x);
if (!l_sub->selected)
selstreams += l_sub->size_mb*512;
}
}
}
}
vidstreams -=selstreams;
return (vidstreams );
}
float k9DVD::getfactor(bool _withMenus,bool _streams,bool _useDvdAuthor) {
if (!_useDvdAuthor || _withMenus) {
//m_dvd.openDevice(Device);
k9CellCopyList *cellCopyList =new k9CellCopyList(&m_dvd,this);
double factor=cellCopyList->getfactor(_withMenus,_streams);
//m_dvd.close();
return (factor);
} else {
float selstreams=0,vidstreams=0,l_factor;
int i,x;
k9DVDTitle *l_track;
k9DVDAudioStream *l_auds;
k9DVDSubtitle *l_sub;
bool withvideo;
double forced=0,forcedsh=0;
for (i=0;i<m_titleCount;i++) {
l_track=gettitle(i);
withvideo=l_track->isSelected() && l_track->getIndexed();
if ( withvideo) {
//size_mb = size of titles - size of unselected chapters
float size_mb=l_track->gettotalsize_mb()-l_track->getChaptersSize_mb( false) ; //gettotalsize_mb does include parts of titles
vidstreams +=size_mb ;
if (l_track->getforceFactor()) {
forced+=size_mb;
forcedsh+=(size_mb/l_track->getfactor());
}
if (_streams) {
for (x=0;x<l_track->audioStreamCount;x++) {
l_auds=l_track->getaudioStream(x);
if (!l_auds->selected)
selstreams += l_auds->size_mb;
}
for (x=0;x<l_track->subPictureCount;x++) {
l_sub=l_track->getsubtitle(x);
if (!l_sub->selected)
selstreams += l_sub->size_mb;
}
}
}
}
vidstreams -=selstreams;
l_factor = ((float) vidstreams - forced) / (k9DVDSize::getMaxSize() - forcedsh);
l_factor = (int)((l_factor+0.01)*100);
l_factor /=100;
if (l_factor <1)
l_factor=1;
return(l_factor);
}
}
void k9DVD::slotVobProgress(unsigned int position,unsigned int total) {
m_progressDlg->setpbTitleStep(position);
m_progressDlg->setpbTitleTotalSteps(total);
tqApp->processEvents();
}
void k9DVD::slotTitleProgress(unsigned int position,unsigned int total) {
m_progressDlg->setpbTotalStep(position);
m_progressDlg->setpbTotalTotalSteps(total);
tqApp->processEvents();
}
void k9DVD::slotTitleText(TQString& text) {
m_progressDlg->setlblTitle(text);
tqApp->processEvents();
}
void k9DVD::slotTotalText(TQString& text) {
m_progressDlg->setlblTotal(text);
tqApp->processEvents();
}
const TQString& k9DVD::getDevice() {
return m_Device;
}
const bool& k9DVD::geterror() {
return m_error;
}
const TQString& k9DVD::geterrMsg() {
return m_errMsg;
}
void k9DVD::setError(const TQString & err) {
m_error=true;
m_errMsg=err;
if (m_progressDlg !=NULL)
m_progressDlg->hide();
}
const bool& k9DVD::getopened() {
return m_opened;
}
TQString &k9DVD::getFormat() {
return (m_format);
}
int k9DVD::getVampsID(int type) {
int abase = 0;
if (type >= 0x80 && type <= 0x87) {
// AC3 audio
abase = 0x80;
} else if (type >= 0x88 && type <= 0x8f) {
// DTS audio
abase = 0x88;
} else if (type >= 0xa0 && type <= 0xbf) {
// LPCM audio
abase = 0xa0;
} else if (type >= 0xc0 && type <= 0xdf) {
// MPEG audio
abase = 0xc0;
}
return (type-abase +1);
}
k9DVDTitle* k9DVD::getstart() {
return m_start;
}
void k9DVD::setstart(k9DVDTitle* title) {
m_start=title;
}
// returns the title number in the reauthored DVD
int k9DVD::getnewTitleNum(k9DVDTitle *title) {
int num=0;
k9DVDTitle *tr;
for (int i=0 ;i < m_titleCount;i++) {
tr=gettitle(i);
if (tr->isSelected() && tr->getIndexed()) {
++num;
if (tr->getnumTitle() == title->getnumTitle())
return(num);
}
}
return(-1);
}
void k9DVD::close() {
m_opened=false;
if (m_dvd.opened())
m_dvd.close();
m_titles.clear();
m_titlesets.clear();
}