Now creates the XML for dvd menues, and multiplex them with the MPEG file

Now allows to send a file to stdin in a process, and store stdout in another file
This commit is contained in:
Sergio Costas 2014-07-24 20:49:23 +02:00
parent 86f77faa3f
commit e404f27e45
7 changed files with 204 additions and 24 deletions

View file

@ -17,7 +17,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>
from gi.repository import GLib
import subprocess
import os
import devede.configuration_data

View file

@ -49,6 +49,8 @@ class create_disk_window:
self.shutdown = wshutdown.get_active()
wcreate_window.destroy()
if (retval == 1):
self.config.final_folder = self.path
self.config.save_config()
return True
else:
return False

View file

@ -21,17 +21,17 @@ import os
import devede.configuration_data
import devede.interface_manager
import devede.message
import devede.mux_dvd_menu
class dvd_menu(devede.interface_manager.interface_manager):
def __init__(self,project):
def __init__(self):
self.entry_vertical_margin = 2.0
self.entry_separation = 2.0
devede.interface_manager.interface_manager.__init__(self)
self.config = devede.configuration_data.configuration.get_config()
self.project = project
self.default_background = os.path.join(self.config.pic_path,"backgrounds","default_bg.png")
self.default_sound = os.path.join(self.config.pic_path,"silence.ogg")
@ -101,10 +101,11 @@ class dvd_menu(devede.interface_manager.interface_manager):
self.update_ui(self.builder)
def show_configuration(self):
def show_configuration(self, file_list):
self.builder = Gtk.Builder()
self.builder.set_translation_domain(self.config.gettext_domain)
self.file_list = file_list
self.refresh_static_data()
@ -270,14 +271,14 @@ class dvd_menu(devede.interface_manager.interface_manager):
""" This method sets data that can't be changed from the dvd settings window.
It must be called before painting a menu """
if self.project.pal:
if self.config.PAL:
self.y=576.0
else:
self.y=480.0
self.title_list = []
counter = 0
for element in self.project.get_all_files():
for element in self.file_list:
if element.show_in_menu:
self.title_list.append( (element, counter) )
counter += 1
@ -289,6 +290,8 @@ class dvd_menu(devede.interface_manager.interface_manager):
def paint_menu(self,paint_background, paint_selected, paint_activated, page_number):
coordinates = []
if self.sf == None:
self.sf=cairo.ImageSurface(cairo.FORMAT_ARGB32,720,int(self.y))
self.cr=cairo.Context(self.sf)
@ -316,9 +319,9 @@ class dvd_menu(devede.interface_manager.interface_manager):
self.cr.restore()
hmargin = self.title_horizontal * 720.0 / 100.0
self.write_text(self.title_text, "title", 0 + hmargin, 720 + hmargin, self.title_vertical * self.y / 100.0, "center")
else:
self.cr.set_source_rgb(1.0,1.0,1.0)
self.cr.paint()
# else:
# self.cr.set_source_rgb(1.0,1.0,1.0)
# self.cr.paint()
top_margin_p = self.y * self.margin_top / 100.0
bottom_margin_p = self.y * self.margin_bottom / 100.0
@ -345,7 +348,9 @@ class dvd_menu(devede.interface_manager.interface_manager):
xl = left_margin_p
xr = 720.0 - right_margin_p
y = top_margin_p + entry_height/2.0
height = (self.cached_menu_size + self.entry_vertical_margin) / 2.0
for entry in self.title_list[page_number*entries_per_page:(page_number+1)*entries_per_page]:
coordinates.append([xl, y-height, xr, y+height, "entry"])
text = entry[0].title_name
if paint_background:
self.paint_base(xl, xr, y, 0)
@ -355,8 +360,10 @@ class dvd_menu(devede.interface_manager.interface_manager):
if paint_activated:
self.write_text(text, "menu_entry_activated", xl, xr, y, self.position_horizontal)
y += entry_height
if paint_arrows:
if page_number == 0:
coordinates.append([xl, y-height, xr, y+height, "right"])
if paint_background:
self.paint_base(xl, xr, y, 0)
self.paint_arrow(xl, xr, y, "menu_entry", False)
@ -365,6 +372,7 @@ class dvd_menu(devede.interface_manager.interface_manager):
if paint_activated:
self.paint_arrow(xl, xr, y, "menu_entry_activated", False)
elif page_number == (self.pages - 1):
coordinates.append([xl, y-height, xr, y+height, "left"])
if paint_background:
self.paint_base(xl, xr, y, 0)
self.paint_arrow(xl, xr, y, "menu_entry", True)
@ -374,6 +382,8 @@ class dvd_menu(devede.interface_manager.interface_manager):
self.paint_arrow(xl, xr, y, "menu_entry_activated", True)
else:
med = (xl + xr) / 2.0
coordinates.append([xl, y-height, med, y+height, "left"])
coordinates.append([med, y-height, xr, y+height, "right"])
if paint_background:
self.paint_base(xl, xr, y, 1)
self.paint_base(xl, xr, y, 2)
@ -385,6 +395,7 @@ class dvd_menu(devede.interface_manager.interface_manager):
if paint_activated:
self.paint_arrow(med, xr, y, "menu_entry_activated", False)
self.paint_arrow(xl, med, y, "menu_entry_activated", True)
return coordinates
def paint_base(self,xl, xr, y, type_b):
@ -435,8 +446,74 @@ class dvd_menu(devede.interface_manager.interface_manager):
cr.set_source_surface(self.sf)
cr.paint()
def create_dvd_menus(self,base_path):
def create_menu_stream(self,path,n_page,coordinates):
""" Creates the menu XML file """
xml_file=open(os.path.join(path,"menu_"+str(n_page)+".xml"),"w")
xml_file.write('<subpictures>\n\t<stream>\n\t\t<spu force="yes" start="00:00:00.00"')# transparent="000000"')
xml_file.write(' image="'+os.path.join(path,"menu_"+str(n_page)+'_unselected_bg.png"'))
xml_file.write(' highlight="'+os.path.join(path,"menu_"+str(n_page)+'_selected_bg.png"'))
xml_file.write(' select="'+os.path.join(path,"menu_"+str(n_page)+'_active_bg.png"'))
xml_file.write(' >\n')
n_elements = 0
has_next = False
has_previous = False
for e in coordinates:
if (e[4] == "entry"):
n_elements += 1
continue
if (e[4] == "right"):
has_next = True
continue
if (e[4] == "left"):
has_previous = True
continue
counter = 0
for element in coordinates:
xl = int(element[0])
yt = int(element[1])
xr = int(element[2])
yb = int(element[3])
if (xl % 2) == 1:
xl += 1
if (yt % 2) == 1:
yt += 1
if (xr % 2) == 1:
xr -= 1
if (yb % 2) == 1:
yb -= 1
xml_file.write('\t\t\t<button name="boton'+str(n_page)+"x"+str(counter))
xml_file.write('" x0="'+str(xl)+'" y0="'+str(yt)+'" x1="'+str(xr)+'" y1="'+str(yb)+'"')
if counter > 0:
xml_file.write(' up="boton'+str(n_page)+"x")
if counter >= n_elements:
xml_file.write(str(n_elements - 1))
else:
xml_file.write(str(counter-1))
xml_file.write('"')
if (counter < (n_elements - 1)) or ((counter < n_elements) and (has_next or has_previous)):
xml_file.write(' down="boton'+str(n_page)+"x")
xml_file.write(str(counter+1))
xml_file.write('"')
if (element[4] == "left") and (has_next):
xml_file.write(' right="boton'+str(n_page)+'x'+str(counter+1)+'"')
if (element[4] == "right") and (has_previous):
xml_file.write(' left="boton'+str(n_page)+'x'+str(counter-1)+'"')
xml_file.write(' > </button>\n')
counter += 1
xml_file.write("</spu>\n</stream>\n</subpictures>\n")
xml_file.close()
return False
def create_dvd_menus(self, file_list, base_path):
self.file_list = file_list
self.refresh_static_data()
cv = devede.converter.converter()
menu_folder = os.path.join(base_path,"menu")
@ -450,7 +527,7 @@ class dvd_menu(devede.interface_manager.interface_manager):
menu_converter = cv.get_menu_converter()
while n_page < self.pages:
self.sf = None
self.paint_menu(True, False, False, n_page)
coordinates = self.paint_menu(True, False, False, n_page)
self.sf.write_to_png(os.path.join(menu_folder,"menu_"+str(n_page)+"_bg.png"))
self.sf = None
self.paint_menu(False, False, False, n_page)
@ -461,9 +538,14 @@ class dvd_menu(devede.interface_manager.interface_manager):
self.sf = None
self.paint_menu(False, False, True, n_page)
self.sf.write_to_png(os.path.join(menu_folder,"menu_"+str(n_page)+"_active_bg.png"))
self.create_menu_stream(menu_folder, n_page, coordinates)
converter = menu_converter()
converter.create_mpg(n_page,self.background_music,self.sound_length,self.project.pal,menu_folder)
converter.create_mpg(n_page,self.background_music,self.sound_length,self.config.PAL,menu_folder)
# add this process without dependencies
processes.append([converter, None])
muxer = devede.mux_dvd_menu.mux_dvd_menu()
muxer.create_mpg(n_page,menu_folder)
# the muxer process depends of the converter process
processes.append([muxer, [converter]])
n_page += 1
return processes

View file

@ -33,11 +33,14 @@ class executor(GObject.GObject):
GObject.GObject.__init__(self)
self.config = devede.configuration_data.configuration.get_config()
self.channel_stdin = None
self.channel_stdout = None
self.channel_stderr = None
self.text = ""
self.stdout_data = ""
self.stderr_data = ""
self.stdin_file = None
self.stdout_file = None
def run(self, progress_bar):
@ -48,7 +51,7 @@ class executor(GObject.GObject):
self.progress_bar[0].show_all()
def remove_ansi(self,line):
output=""
while True:
pos=line.find("\033[") # try with double-byte ESC
@ -59,10 +62,10 @@ class executor(GObject.GObject):
if pos==-1: # no ANSI characters; we ended
output+=line
break
output+=line[:pos]
line=line[pos+jump:]
while True:
if len(line)==0:
break
@ -76,23 +79,60 @@ class executor(GObject.GObject):
def launch_process(self,command):
self.config.append_log("Launching:",False)
self.launch_command = "Launching:"
for e in command:
self.config.append_log(e+" ")
self.launch_command += (e+" ")
self.handle = subprocess.Popen(command,stdout = subprocess.PIPE, stderr = subprocess.PIPE)
if (self.stdin_file != None):
self.handle = subprocess.Popen(command,stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
self.channel_stdin = GLib.IOChannel(self.handle.stdin.fileno())
self.channel_stdin.add_watch(GLib.IO_OUT | GLib.IO_HUP, self.read_stdin_from_file)
self.file_in = open(self.stdin_file,"rb")
else:
self.handle = subprocess.Popen(command,stdout = subprocess.PIPE, stderr = subprocess.PIPE)
self.channel_stdout = GLib.IOChannel(self.handle.stdout.fileno())
self.channel_stderr = GLib.IOChannel(self.handle.stderr.fileno())
self.channel_stdout.add_watch(GLib.IO_IN | GLib.IO_HUP,self.read_stdout)
if (self.stdout_file != None):
self.channel_stdout.add_watch(GLib.IO_IN | GLib.IO_HUP,self.read_stdout_to_file)
self.file_out = open(self.stdout_file,"wb")
else:
self.channel_stdout.add_watch(GLib.IO_IN | GLib.IO_HUP,self.read_stdout)
self.channel_stderr.add_watch(GLib.IO_IN | GLib.IO_HUP,self.read_stderr)
self.stdout_buf = ""
self.stderr_buf = ""
def read_stdout_to_file(self,source,condition):
if (condition != GLib.IO_IN):
self.channel_stdout = None
if ((self.channel_stderr == None) and (self.channel_stdin == None)):
self.wait_end()
return False
else:
line_data = self.handle.stdout.read1(4096)
self.file_out.write(line_data)
return True
def read_stdin_from_file(self,source,condition):
line_data = self.file_in.read1(4096)
if (len(line_data) == 0):
self.channel_stdin = None
self.handle.stdin.close()
if ((self.channel_stderr == None) and (self.channel_stdout == None)):
self.wait_end()
return False
else:
self.handle.stdin.write(line_data)
return True
def read_stdout(self,source,condition):
if (condition != GLib.IO_IN):
self.channel_stdout = None
if (self.channel_stderr == None):
if ((self.channel_stderr == None) and (self.channel_stdin == None)):
self.wait_end()
return False
else:
@ -109,11 +149,12 @@ class executor(GObject.GObject):
self.process_stdout(final_data)
return True
def read_stderr(self,source,condition):
if (condition != GLib.IO_IN):
self.channel_stderr = None
if (self.channel_stdout == None):
if ((self.channel_stdout == None) and (self.channel_stdin == None)):
self.wait_end()
return False
else:
@ -142,6 +183,7 @@ class executor(GObject.GObject):
def wait_end(self):
self.config.append_log(self.text)
self.config.append_log(self.launch_command)
self.config.append_log(self.stdout_data)
self.config.append_log(self.stderr_data)
retval = self.handle.wait()

View file

@ -0,0 +1,54 @@
#!/usr/bin/env python3
# Copyright 2014 (C) Raster Software Vigo (Sergio Costas)
#
# This file is part of DeVeDe-NG
#
# DeVeDe-NG 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 3 of the License, or
# (at your option) any later version.
#
# DeVeDe-NG 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, see <http://www.gnu.org/licenses/>
import os
import devede.configuration_data
import devede.executor
class mux_dvd_menu(devede.executor.executor):
def __init__(self):
devede.executor.executor.__init__(self)
self.config = devede.configuration_data.configuration.get_config()
def create_mpg(self,n_page,output_path):
self.n_page = n_page
self.text = _("Mixing menu %(X)d") % {"X": self.n_page}
self.command_var=[]
self.command_var.append("spumux")
self.command_var.append(os.path.join(output_path,"menu_"+str(n_page)+".xml"))
self.stdin_file = os.path.join(output_path,"menu_"+str(n_page)+".mpg")
self.stdout_file = os.path.join(output_path,"menu_"+str(n_page)+"B.mpg")
def process_stderr(self,data):
print("spumux: "+str(data))
return
pos = data[0].find("time=")
if (pos != -1):
pos+=5
pos2 = data[0].find(" ",pos)
if (pos2 != -1):
t = float(data[0][pos:pos2])
self.progress_bar[1].set_fraction(t / self.sound_length)

View file

@ -33,7 +33,7 @@ class devede_project:
self.config = devede.configuration_data.configuration.get_config()
self.disc_type = self.config.disc_type
self.menu = devede.dvd_menu.dvd_menu(self)
self.menu = devede.dvd_menu.dvd_menu()
self.current_title = None
@ -252,7 +252,7 @@ class devede_project:
def on_menu_options_clicked(self,b):
self.menu.show_configuration()
self.menu.show_configuration(self.get_all_files())
def on_create_disc_clicked(self,b):
@ -262,6 +262,6 @@ class devede_project:
run_window = devede.runner.runner()
p = self.menu.create_dvd_menus(data.path)
p = self.menu.create_dvd_menus(self.get_all_files(), data.path)
run_window.add_processes(p)
run_window.run()