Now copies a file when it is in the final format

Now creates the DVD structure with DVDAuthor

Moved the XML generating code to its own file
This commit is contained in:
Sergio Costas 2014-07-30 23:51:17 +02:00
parent 1373141ecb
commit 54a2dd0b03
5 changed files with 568 additions and 419 deletions

View file

@ -26,6 +26,7 @@ import devede.dvd_menu
import devede.create_disk_window
import devede.runner
import devede.settings
import devede.dvdauthor_converter
class devede_project:
@ -263,10 +264,14 @@ class devede_project:
run_window = devede.runner.runner()
file_movies = self.get_all_files()
final_dependencies = []
if (self.wcreate_menu.get_active()):
processes,menu_entries = self.menu.create_dvd_menus(file_movies, data.path)
for p in processes:
run_window.add_process(p)
final_dependencies.append(p)
else:
menu_entries = None
@ -279,426 +284,25 @@ class devede_project:
for movie in file_movies:
p = movie.do_conversion(os.path.join(movie_folder,"movie_"+str(counter)+".mpg"))
run_window.add_process(p)
final_dependencies.append(p)
counter += 1
if (self.menu.at_startup == "menu_show_at_startup"):
start_with_menu = True
else:
start_with_menu = False
if (self.disc_type == "dvd"):
self.create_dvdauthor_xml(data.path,file_movies,menu_entries, start_with_menu)
if (self.menu.at_startup == "menu_show_at_startup"):
start_with_menu = True
else:
start_with_menu = False
dvdauthor = devede.dvdauthor_converter.dvdauthor_converter()
dvdauthor.create_dvd_project(data.path, data.name, file_movies, menu_entries, start_with_menu)
# dvdauthor must wait until all the files have been converted
for element in final_dependencies:
dvdauthor.add_dependency(element)
run_window.add_process(dvdauthor)
run_window.connect("done",self.disc_done)
self.wmain_window.hide()
run_window.run()
def expand_xml(self,text):
text=text.replace('&','&')
text=text.replace('<','&lt;')
text=text.replace('>','&gt;')
text=text.replace('"','&quot;')
text=text.replace("'",'&apos;')
return text
def create_dvdauthor_xml(self,movie_folder, file_movies, menu_entries, start_with_menu):
xmlpath = os.path.join(movie_folder,"xml_data")
datapath = os.path.join(movie_folder,"dvd_tree")
try:
os.makedirs(xmlpath)
except:
pass
try:
os.makedirs(datapath)
except:
pass
if (len(file_movies) == 1) and (menu_entries == None):
onlyone = True
else:
onlyone = False
if (menu_entries == None):
elements_per_menu = 1000
else:
elements_per_menu = len(menu_entries[0]["chapters"])
xml_file=open(os.path.join(xmlpath,"dvdauthor.xml"),"w")
xml_file.write('<dvdauthor dest="'+datapath+'">\n')
if onlyone:
xml_file.write('\t<vmgm />\n')
else:
xml_file.write('\t<vmgm>\n')
# MENU
# in the FPC we do a jump to the first menu in the first titleset if we wanted MENU
# or we jump to the second titleset if we didn't want MENU at startup
xml_file.write('\t\t<fpc>\n')
xml_file.write('\t\t\tg0=100;\n')
if (menu_entries != None) and (start_with_menu):
xml_file.write('\t\t\tg1=0;\n')
else:
xml_file.write('\t\t\tg1=100;\n')
xml_file.write('\t\t\tg2=1024;\n')
xml_file.write('\t\t\tjump menu 1;\n')
xml_file.write('\t\t</fpc>\n')
# in the VMGM menu we create a code to jump to the title specified in G0
# but if the title is 100, we jump to the menus. There we show the menu number
# contained in G1
xml_file.write("\t\t<menus>\n")
xml_file.write('\t\t\t<video format="')
if self.config.PAL:
xml_file.write("pal")
else:
xml_file.write("ntsc")
xml_file.write('" aspect="4:3"> </video>\n')
xml_file.write('\t\t\t<pgc>\n')
xml_file.write('\t\t\t\t<pre>\n')
counter=1
for element in file_movies:
xml_file.write('\t\t\t\t\tif (g0 eq '+str(counter)+') {\n')
xml_file.write('\t\t\t\t\t\tjump titleset '+str(1+counter)+' menu;\n')
xml_file.write('\t\t\t\t\t}\n')
counter+=1
xml_file.write('\t\t\t\t\tif (g0 eq 100) {\n')
xml_file.write('\t\t\t\t\t\tg2=1024;\n')
xml_file.write('\t\t\t\t\t\tjump titleset 1 menu;\n')
xml_file.write('\t\t\t\t\t}\n')
xml_file.write('\t\t\t\t</pre>\n')
# fake video (one black picture with one second of sound) to ensure 100% compatibility
xml_file.write('\t\t\t\t<vob file="')
if self.config.PAL:
xml_file.write(self.expand_xml(str(os.path.join(self.config.other_path,"base_pal.mpg"))))
else:
xml_file.write(self.expand_xml(str(os.path.join(self.config.other_path,"base_ntsc.mpg"))))
xml_file.write('"></vob>\n')
xml_file.write('\t\t\t</pgc>\n')
xml_file.write('\t\t</menus>\n')
xml_file.write("\t</vmgm>\n")
xml_file.write("\n")
# the first titleset contains all the menus. G1 allows us to jump to the desired menu
xml_file.write('\t<titleset>\n')
xml_file.write('\t\t<menus>\n')
xml_file.write('\t\t\t<video format="')
if self.config.PAL:
xml_file.write("pal")
else:
xml_file.write("ntsc")
xml_file.write('" aspect="4:3"> </video>\n')
first_entry = True
menu_number = 0
counter = 1
title_list = []
for element in file_movies:
if element.show_in_menu:
title_list.append(counter)
counter += 1
if (menu_entries != None):
nmenues = len(menu_entries)
button_counter = 0
for menu_page in menu_entries:
xml_file.write('\t\t\t<pgc>\n')
xml_file.write('\t\t\t\t<pre>\n')
# first we recover the currently selected button
xml_file.write('\t\t\t\t\ts8=g2;\n')
if first_entry: # here we add some code to jump to each menu
for menu2 in range(nmenues-1):
xml_file.write('\t\t\t\t\tif (g1 eq '+str(menu2+1)+') {\n')
xml_file.write('\t\t\t\t\t\tjump menu '+str(menu2+2)+';\n')
xml_file.write('\t\t\t\t\t}\n')
# this code is to fix a bug in some players
xml_file.write('\t\t\t\t\tif (g1 eq 100) {\n')
xml_file.write('\t\t\t\t\t\tjump title 1;\n') #menu '+str(self.nmenues+1)+';\n')
xml_file.write('\t\t\t\t\t}\n')
first_entry = False
xml_file.write('\t\t\t\t</pre>\n')
xml_file.write('\t\t\t\t<vob file="')
xml_file.write(self.expand_xml(menu_page["filename"]))
xml_file.write('></vob>\n')
for nbutton in menu_page["chapters"]:
xml_file.write('\t\t\t\t<button name="'+nbutton+'"> g0='+str(title_list[button_counter])+'; jump vmgm menu; </button>\n')
button_counter+=1
if (menu_page["left"] != None):
xml_file.write('\t\t\t\t<button name="'+menu_page["left"]+'p"> g1=')
xml_file.write(str(menu_number-1))
xml_file.write('; g2=1024; jump menu ')
xml_file.write(str(menu_number))
xml_file.write('; </button>\n')
if (menu_page["right"] != None):
xml_file.write('\t\t\t\t<button name="'+menu_page["right"]+'n"> g1=')
xml_file.write(str(menu_number+1))
xml_file.write('; g2=1024; jump menu ')
xml_file.write(str(menu_number+2))
xml_file.write('; </button>\n')
xml_file.write('\t\t\t\t<post>\n')
xml_file.write('\t\t\t\t\tg2=s8;\n')
xml_file.write('\t\t\t\t\tg1='+str(menu_number)+';\n')
xml_file.write('\t\t\t\t\tjump menu '+str(menu_number+1)+';\n')
xml_file.write('\t\t\t\t</post>\n')
xml_file.write('\t\t\t</pgc>\n')
menu_number += 1
xml_file.write('\t\t</menus>\n')
else:
xml_file.write('\t\t\t<pgc>\n')
xml_file.write('\t\t\t\t<pre>\n')
# first we recover the currently selected button
xml_file.write('\t\t\t\t\ts8=g2;\n')
# this code is to fix a bug in some players
xml_file.write('\t\t\t\t\tif (g1 eq 100) {\n')
xml_file.write('\t\t\t\t\t\tjump title 1;\n') #menu '+str(self.nmenues+1)+';\n')
xml_file.write('\t\t\t\t\t}\n')
xml_file.write('\t\t\t\t</pre>\n')
xml_file.write('\t\t\t\t<vob file="')
if self.config.PAL:
xml_file.write(self.expand_xml(str(os.path.join(self.config.other_path,"base_pal.mpg")))+'"')
else:
xml_file.write(self.expand_xml(str(os.path.join(self.config.other_path,"base_ntsc.mpg")))+'"')
xml_file.write('></vob>\n')
xml_file.write('\t\t\t\t<post>\n')
xml_file.write('\t\t\t\t\tg2=s8;\n')
xml_file.write('\t\t\t\t\tg1=0;\n')
xml_file.write('\t\t\t\t\tjump menu 1;\n')
xml_file.write('\t\t\t\t</post>\n')
xml_file.write('\t\t\t</pgc>\n')
xml_file.write('\t\t</menus>\n')
xml_file.write('\t\t<titles>\n')
xml_file.write('\t\t\t<video format="')
if self.config.PAL:
xml_file.write("pal")
else:
xml_file.write("ntsc")
xml_file.write('" aspect="4:3"> </video>\n')
xml_file.write('\t\t\t<pgc>\n')
xml_file.write('\t\t\t\t<vob file="')
if self.config.PAL:
xml_file.write(self.expand_xml(str(os.path.join(self.config.other_path,"base_pal.mpg"))))
else:
xml_file.write(self.expand_xml(str(os.path.join(self.config.other_path,"base_ntsc.mpg"))))
xml_file.write('"></vob>\n')
xml_file.write('\t\t\t\t<post>\n')
xml_file.write('\t\t\t\t\tg0=1;\n')
xml_file.write('\t\t\t\t\tg1=0;\n')
xml_file.write('\t\t\t\t\tg2=1024;\n')
xml_file.write('\t\t\t\t\tcall vmgm menu entry title;\n')
xml_file.write('\t\t\t\t</post>\n')
xml_file.write('\t\t\t</pgc>\n')
xml_file.write('\t\t</titles>\n')
xml_file.write("\t</titleset>\n")
xml_file.write("\n")
# Now, create the titleset for each video
total_t=len(file_movies)
titleset=1
titles=0
counter=0
for element in file_movies:
files=0
action=element.actions
xml_file.write("\n")
if element.is_mpeg_ps:
# if it's already an MPEG-2 compliant file, we use the original values
if element.original_fps == 25:
pal_ntsc="pal"
ispal=True
else:
pal_ntsc="ntsc"
ispal=False
if element.original_aspect_ratio > 1.6:
faspect='16:9'
fwide=True
else:
faspect='4:3'
fwide=False
else:
# but if we are converting it, we use the desired values
if element.format_pal:
pal_ntsc="pal"
ispal=True
else:
pal_ntsc="ntsc"
ispal=False
if element.aspect_ratio_final > 1.6:
faspect='16:9'
fwide=True
else:
faspect='4:3'
fwide=False
xml_file.write("\t<titleset>\n")
if not onlyone:
xml_file.write("\t\t<menus>\n")
xml_file.write('\t\t\t<video format="'+pal_ntsc+'" aspect="'+faspect+'"')
if fwide:
xml_file.write(' widescreen="nopanscan"')
xml_file.write('> </video>\n')
xml_file.write("\t\t\t<pgc>\n")
xml_file.write("\t\t\t\t<pre>\n")
xml_file.write('\t\t\t\t\tif (g0 eq 100) {\n')
xml_file.write('\t\t\t\t\t\tjump vmgm menu entry title;\n')
xml_file.write('\t\t\t\t\t}\n')
xml_file.write('\t\t\t\t\tg0=100;\n')
xml_file.write('\t\t\t\t\tg1='+str(int(titles/elements_per_menu))+';\n')
xml_file.write('\t\t\t\t\tjump title 1;\n')
xml_file.write('\t\t\t\t</pre>\n')
# fake video to ensure compatibility
xml_file.write('\t\t\t\t<vob file="')
if ispal:
xml_file.write(self.expand_xml(str(os.path.join(self.config.other_path,"base_pal"))))
else:
xml_file.write(self.expand_xml(str(os.path.join(self.config.other_path,"base_ntsc"))))
if fwide:
xml_file.write("_wide")
xml_file.write('.mpg"></vob>\n')
xml_file.write("\t\t\t</pgc>\n")
xml_file.write("\t\t</menus>\n")
xml_file.write("\t\t<titles>\n")
xml_file.write('\t\t\t<video format="'+pal_ntsc+'" aspect="'+faspect+'"')
if fwide:
xml_file.write(' widescreen="nopanscan"')
xml_file.write('> </video>\n')
# subtitles part
# for element3 in element2["sub_list"]:
# xml_file.write('\t\t\t<subpicture lang="'+self.expand_xml(str(element3["sub_language"][:2].lower()))+'" />\n')
xml_file.write('\t\t\t<pgc>\n')
# if (element2["force_subs"]) and (len(element2["sub_list"])!=0):
# xml_file.write('\t\t\t\t<pre>\n')
# xml_file.write('\t\t\t\t\tsubtitle=64;\n')
# xml_file.write('\t\t\t\t</pre>\n')
xml_file.write('\t\t\t\t<vob file="'+self.expand_xml(element.converted_filename)+'" ')
xml_file.write('chapters="0')
if (element.original_length > 5):
if (element.divide_in_chapters): # add chapters
toadd = element.chapter_size
seconds = toadd*60
while seconds < (element.original_length - 4):
thetime = self.return_time(seconds,False)
xml_file.write(","+thetime)
seconds += (toadd*60)
xml_file.write(',' + self.return_time((element.original_length -2 ),False))
xml_file.write('" />\n')
if not onlyone:
xml_file.write('\t\t\t\t<post>\n')
files+=1
xml_file.write('\t\t\t\t\tg1='+str(int(titles/elements_per_menu))+';\n')
if (action=="action_stop"):
xml_file.write('\t\t\t\t\tg0=100;\n')
xml_file.write('\t\t\t\t\tcall vmgm menu entry title;\n')
else:
xml_file.write('\t\t\t\t\tg0=')
if action=="action_play_previous":
if titles == 0:
prev_t = total_t - 1
else:
prev_t = titles - 1
xml_file.write(str(title_list[prev_t]))
elif action=="action_play_again":
xml_file.write(str(title_list[titles]))
elif action=="action_play_next":
if titles==total_t-1:
next_t=0
else:
next_t=titles+1
xml_file.write(str(title_list[next_t]))
elif action=="action_play_last":
xml_file.write(str(title_list[total_t-1]))
else:
xml_file.write('1') # first
xml_file.write(';\n')
xml_file.write('\t\t\t\t\tcall vmgm menu entry title;\n')
xml_file.write('\t\t\t\t</post>\n')
xml_file.write("\t\t\t</pgc>\n")
xml_file.write("\t\t</titles>\n")
xml_file.write("\t</titleset>\n")
counter+=1
titles+=1
xml_file.write("</dvdauthor>")
xml_file.close()
def return_time(self,seconds,empty):
""" cuts a time in seconds into seconds, minutes and hours """
seconds2=int(seconds)
hours=str(int(seconds2/3600))
if empty:
if len(hours)==1:
hours="0"+hours
else:
if hours=="0":
hours=""
if hours!="":
hours+=":"
minutes=str(int((seconds2/60)%60))
if empty or (hours!=""):
if len(minutes)==1:
minutes="0"+minutes
elif (minutes=="0") and (hours==""):
minutes=""
if minutes!="":
minutes+=":"
secs=str(int(seconds2%60))
if (len(secs)==1) and (minutes!=""):
secs="0"+secs
return hours+minutes+secs
def disc_done(self,object,value):