///////////////////////////////////////////////////////////////////////////// // Name: DVD.cpp // Purpose: The class to store a DVD Structure (Titles/Menus) // Author: Alex Thuering // Created: 29.01.2003 // RCS-ID: $Id: DVD.cpp,v 1.33 2007/03/08 20:22:52 ntalex Exp $ // Copyright: (c) Alex Thuering // Licence: GPL ///////////////////////////////////////////////////////////////////////////// #include "DVD.h" #include "Config.h" #include #include #include #define DATA_FILE(fname) wxFindDataFile(_T("data") + wxString(wxFILE_SEP_PATH) + fname) //////////////////////////////// TextSub //////////////////////////////////// TextSub::TextSub(wxString filename) { m_filename = filename; m_characterSet = wxT("ISO8859-1"); m_font = wxT("arial.ttf"); m_fontSize = 28; m_hAlignment = wxT("left"); m_vAlignment = wxT("bottom"); m_leftMargin = 60; m_rightMargin = 60; m_topMargin = 20; m_bottomMargin = 30; m_subtitleFps = 25; m_movieFps = 25; m_movieWidth = 720; m_movieHeight = 574; } wxXmlNode* TextSub::GetXML(DVDFileType type) { wxXmlNode* textsubNode = new wxXmlNode(wxXML_ELEMENT_NODE, _T("textsub")); textsubNode->AddProperty(_T("filename"), m_filename); if (m_characterSet != wxT("ISO8859-1")) textsubNode->AddProperty(_T("characterset"), m_characterSet); if (m_font != wxT("arial.ttf")) // || type == DVDAUTHOR_XML textsubNode->AddProperty(_T("font"), m_font); if (m_fontSize != 28) textsubNode->AddProperty(_T("fontsize"), wxString::Format(wxT("%g"), m_fontSize)); if (m_hAlignment != wxT("left")) textsubNode->AddProperty(_T("horizontal-alignment"), m_hAlignment); if (m_vAlignment != wxT("bottom")) textsubNode->AddProperty(_T("vertical-alignment"), m_vAlignment); if (m_leftMargin != 60) textsubNode->AddProperty(_T("left-margin"), wxString::Format(wxT("%d"), m_leftMargin)); if (m_rightMargin != 60) textsubNode->AddProperty(_T("right-margin"), wxString::Format(wxT("%d"), m_rightMargin)); if (m_topMargin != 20) textsubNode->AddProperty(_T("top-margin"), wxString::Format(wxT("%d"), m_topMargin)); if (m_bottomMargin != 30) textsubNode->AddProperty(_T("bottom-margin"), wxString::Format(wxT("%d"), m_bottomMargin)); if (m_subtitleFps != 25) textsubNode->AddProperty(_T("subtitle-fps"), wxString::Format(wxT("%g"), m_subtitleFps)); if (m_movieFps != 25) textsubNode->AddProperty(_T("movie-fps"), wxString::Format(wxT("%g"), m_movieFps)); if (m_movieWidth != 720) textsubNode->AddProperty(_T("movie-width"), wxString::Format(wxT("%d"), m_movieWidth)); if (m_movieHeight != 574) textsubNode->AddProperty(_T("movie-height"), wxString::Format(wxT("%d"), m_movieHeight)); return textsubNode; } bool TextSub::PutXML(wxXmlNode* node) { wxString val; long lval; double dval; if (!node->GetPropVal(wxT("filename"), &m_filename)) return false; node->GetPropVal(wxT("characterset"), &m_characterSet); node->GetPropVal(wxT("font"), &m_font); if (node->GetPropVal(wxT("fontsize"), &val) && val.ToDouble(&dval)) m_fontSize = dval; node->GetPropVal(wxT("horizontal-alignment"), &m_hAlignment); node->GetPropVal(wxT("vertical-alignment"), &m_vAlignment); if (node->GetPropVal(wxT("left-margin"), &val) && val.ToLong(&lval)) m_leftMargin = lval; if (node->GetPropVal(wxT("right-margin"), &val) && val.ToLong(&lval)) m_rightMargin = lval; if (node->GetPropVal(wxT("top-margin"), &val) && val.ToLong(&lval)) m_topMargin = lval; if (node->GetPropVal(wxT("bottom-margin"), &val) && val.ToLong(&lval)) m_bottomMargin = lval; if (node->GetPropVal(wxT("subtitle-fps"), &val) && val.ToDouble(&dval)) m_subtitleFps = dval; if (node->GetPropVal(wxT("movie-fps"), &val) && val.ToDouble(&dval)) m_movieFps = dval; if (node->GetPropVal(wxT("movie-width"), &val) && val.ToLong(&lval)) m_movieWidth = lval; if (node->GetPropVal(wxT("movie-height"), &val) && val.ToLong(&lval)) m_movieHeight = lval; return true; } bool TextSub::SaveSpumux(wxString filename) { wxXmlDocument xml; wxXmlNode* root = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("subpictures")); wxXmlNode* streamNode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("stream")); streamNode->AddChild(GetXML(DVDAUTHOR_XML)); root->AddChild(streamNode); xml.SetRoot(root); return xml.Save(filename); } ////////////////////////////////// Vob ////////////////////////////////////// Vob::~Vob() { if (m_menu) delete m_menu; if (m_slideshow) delete m_slideshow; WX_CLEAR_ARRAY(m_subtitles) } wxXmlNode* Vob::GetXML(DVDFileType type, DVD* dvd) { wxXmlNode* node = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("vob")); wxString fname = GetFilename(); if (type == DVDAUTHOR_XML && GetTmpFilename().length()) fname = GetTmpFilename(); if (fname.length()) node->AddProperty(wxT("file"), fname); if (type == DVDSTYLER_XML) { if (GetVideoFilename().length()) XmlWriteValue(node, wxT("video"), GetVideoFilename()); for (unsigned int i=0; iAddChild(new wxXmlNode(wxXML_TEXT_NODE, wxEmptyString, GetAudioFilenames()[i])); node->AddChild(audioNode); } for (unsigned int i=0; iAddChild(GetSubtitles()[i]->GetXML(type)); } if (GetPause() != 0) { wxString pause = wxT("inf"); if (GetPause()>0) pause = wxString::Format(wxT("%d"), GetPause()); node->AddProperty(wxT("pause"), pause); } if (GetChapters().length() && !GetSlideshow()) node->AddProperty(wxT("chapters"), GetChapters()); if (GetMenu() && type == DVDSTYLER_XML) node->AddChild(GetMenu()->GetXML(type)); if (GetSlideshow()) { if (type == DVDSTYLER_XML) node->AddChild(GetSlideshow()->GetXML(type)); else if (type == DVDAUTHOR_XML) { wxString chapters; int t = 1; for (unsigned i=1; iCount(); i++) { t += GetSlideshow()->GetDuration(); int h = t/3600; int m = (t%3600)/60; int s = t%60; if (chapters.length()) chapters += wxT(","); chapters += wxString::Format(wxT("%d:%2d:%2d.1"), h, m, s); } node->AddProperty(wxT("chapters"), chapters); } } return node; } bool Vob::PutXML(wxXmlNode* node) { wxString val; long lval; node->GetPropVal(wxT("file"), &m_filename); wxXmlNode* child = node->GetChildren(); while (child) { if (child->GetName() == wxT("video")) SetVideoFilename(child->GetChildren()->GetContent()); else if (child->GetName() == wxT("audio")) GetAudioFilenames().Add(child->GetChildren()->GetContent()); else if (child->GetName() == wxT("textsub")) { TextSub* textsub = new TextSub; textsub->PutXML(child); GetSubtitles().Add(textsub); } else if (child->GetName() == wxT("menu")) { m_menu = new Menu(); if (!m_menu->PutXML(child)) return false; } else if (child->GetName() == wxT("slideshow")) m_slideshow = new Slideshow(child); child = child->GetNext(); } if (node->GetPropVal(wxT("pause"), &val)) { if (val == wxT("inf")) m_pause = -1; else if (val.ToLong(&lval)) m_pause = int(lval); } node->GetPropVal(wxT("chapters"), &m_chapters); return true; } unsigned int Vob::GetFileSize(wxString filename) { wxStructStat fInfo; if (wxStat(filename, &fInfo) != 0) return 0; return fInfo.st_size/1024; } int Vob::GetSize(bool generated) { if (generated) { if (GetTmpFilename().length()) return GetFileSize(GetTmpFilename()); else if (GetFilename().length()) return GetFileSize(GetFilename()); return 0; } int size = 0; if (GetMenu()) size += 250; else if (GetSlideshow()) size += 150*GetSlideshow()->GetDuration()*GetSlideshow()->Count(); else if (GetFilename().length()) size += GetFileSize(GetFilename()); else { if (GetVideoFilename().length()) size += GetFileSize(GetVideoFilename()); for (unsigned int i=0; iGetFilename()); } return size; } Vob* Vob::CreateEmptyVob(VideoFormat videoFormat, AudioFormat audioFormat) { wxString filename = wxT("empty_pal_mp2.mpg"); if (videoFormat == vfNTSC) { filename = audioFormat == afMP2 ? wxT("empty_ntsc_mp2.mpg") : wxT("empty_ntsc_ac3.mpg"); } else if (audioFormat != afMP2) { filename = wxT("empty_pal_ac3.mpg"); } return new Vob(DATA_FILE(filename)); } ////////////////////////////////// Pgc ////////////////////////////////////// Menu* Pgc::GetMenu() { for (int i=0; i<(int)GetVobs().GetCount(); i++) if (GetVobs()[i]->GetMenu()) return GetVobs()[i]->GetMenu(); return NULL; } Slideshow* Pgc::GetSlideshow() { for (int i=0; i<(int)GetVobs().GetCount(); i++) if (GetVobs()[i]->GetSlideshow()) return GetVobs()[i]->GetSlideshow(); return NULL; } wxXmlNode* Pgc::GetXML(DVDFileType type, DVD* dvd, wxString nextTitle) { wxXmlNode* node = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("pgc")); if (m_entry.length()) node->AddProperty(wxT("entry"), m_entry); if (GetMenu() && type == DVDAUTHOR_XML) GetMenu()->GetXML(type, dvd->GetPlayAllRegister(), node); if (GetSlideshow() && type == DVDAUTHOR_XML) GetSlideshow()->GetXML(type, node); for (int i=0; i<(int)GetVobs().GetCount(); i++) node->AddChild(GetVobs()[i]->GetXML(type, dvd)); if (GetPreCommands().length()) XmlWriteValue(node, wxT("pre"), GetPreCommands()); wxString postCommands = GetPostCommands(); if (dvd->GetPlayAllRegister() != -1 && nextTitle.length()) { wxString g = wxT("g") + wxString::Format(wxT("%d"),dvd->GetPlayAllRegister()); postCommands = wxT("if (") + g + wxT("==1) jump ") + nextTitle + wxT(";") + postCommands; } if (postCommands.length()) XmlWriteValue(node, wxT("post"), postCommands); return node; } bool Pgc::PutXML(wxXmlNode* node) { WX_CLEAR_ARRAY(GetVobs()); wxString val; node->GetPropVal(wxT("entry"), &m_entry); wxXmlNode* child = node->GetChildren(); Menu* menu = NULL; // old while (child) { if (child->GetName() == wxT("spumux")) // get spunode (old) { menu = new Menu(); menu->PutXML(child); } else if (child->GetName() == wxT("vob")) // get vob { Vob* vob; if (menu) vob = new Vob(menu); else vob = new Vob(wxT("")); menu = NULL; if (vob->PutXML(child)) GetVobs().Add(vob); else { delete vob; wxLogError(_("Can't load vob")); return false; } } else if (child->GetName() == wxT("pre")) // get pre commands SetPreCommands(child->GetChildren()->GetContent()); else if (child->GetName() == wxT("post")) // get post commands SetPostCommands(child->GetChildren()->GetContent()); child = child->GetNext(); } return true; } ////////////////////////////// Audio/Video /////////////////////////////////// wxArrayString Audio::GetFormatStrings(wxString def) { wxArrayString ret; ret.Add(def); ret.Add(wxT("mp2")); ret.Add(wxT("ac3")); ret.Add(wxT("dts")); ret.Add(wxT("pcm")); return ret; } wxArrayString Audio::GetQuantStrings(wxString def) { wxArrayString ret; ret.Add(def); ret.Add(wxT("16bps")); ret.Add(wxT("20bps")); ret.Add(wxT("24bps")); ret.Add(wxT("drc")); return ret; } wxArrayString Audio::GetDolbyStrings(wxString def) { wxArrayString ret; ret.Add(def); ret.Add(wxT("surround")); return ret; } wxArrayString Audio::GetSamplerateStrings(wxString def) { wxArrayString ret; ret.Add(def); ret.Add(wxT("48khz")); ret.Add(wxT("96khz")); return ret; } wxXmlNode* Audio::GetXML(DVDFileType type) { wxXmlNode* node = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("audio")); if (m_format.length()) node->AddProperty(wxT("format"), m_format); if (m_channels >= 0) node->AddProperty(wxT("channels"), wxString::Format(wxT("%d"), m_channels)); if (m_quant.length()) node->AddProperty(wxT("quant"), m_quant); if (m_dolby.length()) node->AddProperty(wxT("dolby"), m_dolby); if (m_samplerate.length()) node->AddProperty(wxT("samplerate"), m_samplerate); if (m_lang.length()) node->AddProperty(wxT("lang"), m_lang); if (node->GetProperties() == NULL) { delete node; node = NULL; } return node; } bool Audio::PutXML(wxXmlNode* node) { if (node == NULL || node->GetName() != wxT("audio")) return false; wxString val; long lval; node->GetPropVal(wxT("format"), &m_format); if (node->GetPropVal(wxT("channels"), &val) && val.ToLong(&lval)) m_channels = int(lval); node->GetPropVal(wxT("quant"), &m_quant); node->GetPropVal(wxT("dolby"), &m_dolby); node->GetPropVal(wxT("samplerate"), &m_samplerate); node->GetPropVal(wxT("lang"), &m_lang); return true; } wxArrayString Video::GetFormatStrings(wxString def) { wxArrayString ret; ret.Add(def); ret.Add(wxT("pal")); ret.Add(wxT("ntsc")); return ret; } wxArrayString Video::GetAspectStrings(wxString def) { wxArrayString ret; ret.Add(def); ret.Add(wxT("4:3")); ret.Add(wxT("16:9")); return ret; } wxArrayString Video::GetWidescreenStrings(wxString def) { wxArrayString ret; ret.Add(def); ret.Add(wxT("nopanscan")); ret.Add(wxT("noletterbox")); return ret; } wxXmlNode* Video::GetXML(DVDFileType type) { wxXmlNode* node = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("video")); if (m_format.length()) node->AddProperty(wxT("format"), m_format); if (m_aspect.length()) node->AddProperty(wxT("aspect"), m_aspect); if (m_resolution.length()) node->AddProperty(wxT("resolution"), m_resolution); if (m_caption.length()) node->AddProperty(wxT("caption"), m_caption); if (m_widescreen.length()) node->AddProperty(wxT("widescreen"), m_widescreen); if (node->GetProperties() == NULL) { delete node; node = NULL; } return node; } bool Video::PutXML(wxXmlNode* node) { if (node == NULL || node->GetName() != wxT("video")) return false; wxString val; node->GetPropVal(wxT("format"), &m_format); node->GetPropVal(wxT("aspect"), &m_aspect); node->GetPropVal(wxT("resolution"), &m_resolution); node->GetPropVal(wxT("caption"), &m_caption); node->GetPropVal(wxT("widescreen"), &m_widescreen); return true; } ////////////////////////////////// Menus ////////////////////////////////////// wxXmlNode* Menus::GetXML(DVDFileType type, DVD* dvd) { wxXmlNode* node = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("menus")); if (GetAudio().GetXML(type)) node->AddChild(GetAudio().GetXML(type)); if (GetVideo().GetXML(type)) node->AddChild(GetVideo().GetXML(type)); for (int i=0; i<(int)GetCount(); i++) node->AddChild((*this)[i]->GetXML(type, dvd, wxT(""))); return node; } bool Menus::PutXML(wxXmlNode* node) { if (node == NULL || node->GetName() != wxT("menus")) return false; WX_CLEAR_ARRAY(*this); wxXmlNode* child = node->GetChildren(); while (child) { if (child->GetName() == wxT("audio")) GetAudio().PutXML(child); else if (child->GetName() == wxT("video")) GetVideo().PutXML(child); else if (child->GetName() == wxT("pgc")) { Pgc* pgc = new Pgc; if (pgc->PutXML(child)) Add(pgc); else { delete pgc; wxLogError(_("Can't load pgc")); return false; } } child = child->GetNext(); } return true; } ////////////////////////////////// Titles //////////////////////////////////// wxXmlNode* Titles::GetXML(DVDFileType type, DVD* dvd, int nextTitleset) { wxXmlNode* node = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("titles")); if (GetAudio().GetXML(type)) node->AddChild(GetAudio().GetXML(type)); if (GetVideo().GetXML(type)) node->AddChild(GetVideo().GetXML(type)); for (int i=0; i<(int)GetCount(); i++) { wxString nextTitle; if (i != (int)GetCount()-1) nextTitle = wxString::Format(wxT("title %d"), i+2); else if (nextTitleset != -1) nextTitle = wxString::Format(wxT("titleset %d title 1"),nextTitleset); node->AddChild((*this)[i]->GetXML(type, dvd, nextTitle)); } return node; } bool Titles::PutXML(wxXmlNode* node) { if (node == NULL || node->GetName() != wxT("titles")) return false; wxXmlNode* child = node->GetChildren(); while (child) { if (child->GetName() == wxT("audio")) GetAudio().PutXML(child); else if (child->GetName() == wxT("video")) GetVideo().PutXML(child); else if (child->GetName() == wxT("pgc")) { Pgc* pgc = new Pgc; if (pgc->PutXML(child)) Add(pgc); else { delete pgc; wxLogError(_("Can't load pgc")); return false; } } child = child->GetNext(); } return true; } ////////////////////////////////// Titleset ////////////////////////////////// wxXmlNode* Titleset::GetXML(DVDFileType type, DVD* dvd, int nextTitleset) { wxXmlNode* node = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("titleset")); if (m_menus.Count() || type != DVDAUTHOR_XML) node->AddChild(m_menus.GetXML(type, dvd)); else if (dvd->IsEmptyMenuEnabled() && dvd->GetVmgm().Count()) { // create empty menu with post command Menus menus; Pgc* pgc = new Pgc; pgc->SetPreCommands(wxT("jump vmgm menu;")); pgc->GetVobs().Add(Vob::CreateEmptyVob(dvd->GetVideoFormat(), dvd->GetAudioFormat())); menus.Add(pgc); node->AddChild(menus.GetXML(type, dvd)); } node->AddChild(m_titles.GetXML(type, dvd, nextTitleset)); return node; } bool Titleset::PutXML(wxXmlNode* node) { if (node == NULL || node->GetName() != wxT("titleset")) return false; wxXmlNode* child = node->GetChildren(); while (child) { if (child->GetName() == wxT("menus")) { if (!GetMenus().PutXML(child)) { wxLogError(_("Can't load menus")); return false; } } else if (child->GetName() == wxT("titles")) { if (!GetTitles().PutXML(child)) { wxLogError(_("Can't load titles")); return false; } } child = child->GetNext(); } return true; } ////////////////////////////////// DVD ////////////////////////////////////// DVD::DVD() { m_name = s_config.GetDefVolumeName(); m_jumppad = true; m_emptyMenu = true; m_playAllRegister = -1; } DVD::~DVD() { WX_CLEAR_ARRAY(m_vmgm); WX_CLEAR_ARRAY(m_titlesets); } int DVD::AddTitleset() { Titleset* titleset = new Titleset; GetTitlesets().Add(titleset); return GetTitlesets().Count(); } int DVD::AddMenu(VideoFormat format, int tsi) { Menu* menu = new Menu((VideoFormat)format); Vob* vob = new Vob(menu); vob->SetPause(-1); Pgc* pgc = new Pgc; pgc->GetVobs().Add(vob); PgcArray& pgcs = GetPgcArray(tsi, true); if (pgcs.GetCount() == 0) // set aspect ratio pgcs.GetVideo().SetAspect(wxT("4:3")); pgcs.Add(pgc); return pgcs.Count()-1; } int DVD::AddPgc(int tsi, bool menu, Pgc* pgc) { if (!pgc) pgc = new Pgc; PgcArray& pgcs = GetPgcArray(tsi, menu); pgcs.Add(pgc); return pgcs.Count()-1; } PgcArray& DVD::GetPgcArray(int tsi, bool menus) { if (tsi>=0 && tsi<(int)GetTitlesets().Count()) { Titleset* ts = GetTitlesets()[tsi]; if (menus) return ts->GetMenus(); else return ts->GetTitles(); } return GetVmgm(); } Vob* DVD::GetVob(int tsi, bool isMenu, int pgci, int vobi) { PgcArray& pgcs = GetPgcArray(tsi, isMenu); if (pgci<0 || pgci>=(int)pgcs.Count()) return NULL; if (vobi<0 || vobi>=(int)pgcs[pgci]->GetVobs().Count()) return NULL; return pgcs[pgci]->GetVobs()[vobi]; } Vob* DVD::GetMenuVob(int tsi, int pgci) { PgcArray& pgcs = GetPgcArray(tsi, true); if (pgci<0 || pgci>=(int)pgcs.Count()) return NULL; // find vob with menu for (int vobi = 0; vobi<(int)pgcs[pgci]->GetVobs().GetCount(); vobi++) { if (pgcs[pgci]->GetVobs()[vobi]->GetMenu() != NULL) return pgcs[pgci]->GetVobs()[vobi]; } return NULL; } Menu* DVD::GetMenu(int tsi, int pgci) { Vob* vob = GetMenuVob(tsi, pgci); if (vob) return vob->GetMenu(); return NULL; } bool DVD::Open(wxString fname) { WX_CLEAR_ARRAY(GetTitlesets()); wxXmlDocument xml; if (!xml.Load(fname)) { wxLogError(_("Can't load xml-file")); return false; } wxXmlNode* root = xml.GetRoot(); if (root == NULL || root->GetName() != wxT("dvdstyler")) { wxLogError(_("This is not a DVDStyler project file")); return false; } root->GetPropVal(wxT("name"), &m_name); wxString val; long lval; if (root->GetPropVal(wxT("jumppad"), &val) && val.ToLong(&lval)) m_jumppad = int(lval); if (root->GetPropVal(wxT("emptyMenu"), &val) && val.ToLong(&lval)) m_emptyMenu = int(lval); if (root->GetPropVal(wxT("videoFormat"), &val) && val.ToLong(&lval)) m_videoFormat = VideoFormat(lval); if (root->GetPropVal(wxT("audioFormat"), &val) && val.ToLong(&lval)) m_audioFormat = AudioFormat(lval); wxXmlNode* child = root->GetChildren(); while (child) { if (child->GetName() == wxT("vmgm")) { if (!GetVmgm().PutXML(child->GetChildren())) { wxLogError(_("Can't load vmgm menus")); return false; } } else if (child->GetName() == wxT("titleset")) { Titleset* titleset = new Titleset; if (titleset->PutXML(child)) GetTitlesets().Add(titleset); else { delete titleset; wxLogError(_("Can't load titleset")); return false; } } child = child->GetNext(); } return true; } bool DVD::Save(wxString fname) { m_playAllRegister = -1; wxXmlDocument xml; wxXmlNode* root = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("dvdstyler")); root->AddProperty(wxT("format"), wxT("2")); root->AddProperty(wxT("name"), GetName()); root->AddProperty(wxT("jumppad"), m_jumppad ? wxT("1") : wxT("0")); root->AddProperty(wxT("emptyMenu"), m_emptyMenu ? wxT("1") : wxT("0")); root->AddProperty(wxT("videoFormat"), wxString::Format(wxT("%d"), m_videoFormat)); root->AddProperty(wxT("audioFormat"), wxString::Format(wxT("%d"), m_audioFormat)); wxXmlNode* vmgmNode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("vmgm")); vmgmNode->AddChild(GetVmgm().GetXML(DVDSTYLER_XML, this)); root->AddChild(vmgmNode); for (int i=0; i<(int)m_titlesets.GetCount(); i++) if (m_titlesets[i]->GetMenus().Count() || m_titlesets[i]->GetTitles().Count()) root->AddChild(m_titlesets[i]->GetXML(DVDSTYLER_XML, this)); xml.SetRoot(root); return xml.Save(fname); } bool DVD::SaveDVDAuthor(wxString fname) { // check if we need "play all" if (HasPlayAllButton()) m_playAllRegister = FindFreeRegister(); // save config for dvdauthor wxXmlDocument xml; wxXmlNode* root = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("dvdauthor")); root->AddProperty(wxT("jumppad"), m_jumppad ? wxT("1") : wxT("0")); wxXmlNode* vmgmNode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("vmgm")); if (GetVmgm().Count()) vmgmNode->AddChild(GetVmgm().GetXML(DVDAUTHOR_XML, this)); else if (IsEmptyMenuEnabled() && GetTitlesets().Count() && GetTitlesets()[0]->GetMenus().Count()) { // create empty vmgm with post command Menus menus; Pgc* pgc = new Pgc; pgc->SetPreCommands(wxT("jump titleset 1 menu;")); pgc->GetVobs().Add(Vob::CreateEmptyVob(GetVideoFormat(), GetAudioFormat())); menus.Add(pgc); vmgmNode->AddChild(menus.GetXML(DVDAUTHOR_XML, this)); } root->AddChild(vmgmNode); for (int i=0; i<(int)m_titlesets.GetCount(); i++) { int nextTitleset = i<(int)m_titlesets.GetCount()-1 && !m_titlesets[i+1]->IsEmpty() ? i+2 : -1; if (!m_titlesets[i]->IsEmpty()) root->AddChild(m_titlesets[i]->GetXML(DVDAUTHOR_XML, this, nextTitleset)); } xml.SetRoot(root); return xml.Save(fname); } int DVD::GetSize(bool generated) { int size = 0; for (int tsi = -1; tsi<(int)GetTitlesets().Count(); tsi++) { for (int m=0; m<=1; m++) { bool menu = m == 0; if (tsi == -1 && !menu) // "titleset -1" contains only vmMenus break; PgcArray& pgcs = GetPgcArray(tsi, menu); for (int pgci = 0; pgci<(int)pgcs.Count(); pgci++) { Pgc* pgc = pgcs[pgci]; for (int vobi = 0; vobi<(int)pgc->GetVobs().Count(); vobi++) size += pgc->GetVobs()[vobi]->GetSize(generated); } } } return size; } bool DVD::HasPlayAllButton() { for (int tsi = -1; tsi<(int)GetTitlesets().Count(); tsi++) { PgcArray& pgcs = GetPgcArray(tsi, true); for (int pgci = 0; pgci<(int)pgcs.Count(); pgci++) { Pgc* pgc = pgcs[pgci]; for (int vobi = 0; vobi<(int)pgc->GetVobs().Count(); vobi++) { Vob* vob = pgc->GetVobs()[vobi]; if (vob->GetMenu()) { Menu* menu = vob->GetMenu(); for (int obji = 0; obji<(int)menu->GetObjectsCount(); obji++) if (menu->GetObject(obji)->IsPlayAll()) return true; } } } } return false; } int DVD::FindFreeRegister() { for (int g=0; g<=12; g++) { if (!IsRegisterUsed(g)) return g; } return -1; } bool DVD::IsRegisterUsed(int g) { wxString gstr = wxT("g") + wxString::Format(wxT("%d"),g); for (int tsi = -1; tsi<(int)GetTitlesets().Count(); tsi++) { for (int m=0; m<=1; m++) { bool menu = m == 0; if (tsi == -1 && !menu) // "titleset -1" contains only vmMenus continue; PgcArray& pgcs = GetPgcArray(tsi, menu); for (int pgci = 0; pgci<(int)pgcs.Count(); pgci++) { Pgc* pgc = pgcs[pgci]; if (pgc->GetPostCommands().Find(gstr) != -1 || pgc->GetPreCommands().Find(gstr) != -1) return true; for (int vobi = 0; vobi<(int)pgc->GetVobs().Count(); vobi++) { Vob* vob = pgc->GetVobs()[vobi]; if (vob->GetMenu()) { Menu* menu = vob->GetMenu(); for (int obji = 0; obji<(int)menu->GetObjectsCount(); obji++) { MenuObject* obj = menu->GetObject(obji); if (obj->HasCustomAction() && obj->GetCustomAction().Find(gstr) != -1) return true; } } } } } } return false; } wxArrayString DVD::GetVideoFormatStrings() { wxArrayString formats; formats.Add(_T("PAL 720x576")); formats.Add(_T("NTSC 720x480")); return formats; } wxArrayString DVD::GetAudioFormatStrings() { wxArrayString formats; formats.Add(_T("MP2")); formats.Add(_T("AC3")); return formats; }