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

@ -6,6 +6,7 @@
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="title" translatable="yes">Creating...</property> <property name="title" translatable="yes">Creating...</property>
<property name="resizable">False</property> <property name="resizable">False</property>
<property name="modal">True</property>
<property name="window_position">center</property> <property name="window_position">center</property>
<property name="icon_name">devede.svg</property> <property name="icon_name">devede.svg</property>
<property name="deletable">False</property> <property name="deletable">False</property>

View file

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

View file

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

View file

@ -21,17 +21,17 @@ import os
import devede.configuration_data import devede.configuration_data
import devede.interface_manager import devede.interface_manager
import devede.message import devede.message
import devede.mux_dvd_menu
class dvd_menu(devede.interface_manager.interface_manager): class dvd_menu(devede.interface_manager.interface_manager):
def __init__(self,project): def __init__(self):
self.entry_vertical_margin = 2.0 self.entry_vertical_margin = 2.0
self.entry_separation = 2.0 self.entry_separation = 2.0
devede.interface_manager.interface_manager.__init__(self) devede.interface_manager.interface_manager.__init__(self)
self.config = devede.configuration_data.configuration.get_config() 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_background = os.path.join(self.config.pic_path,"backgrounds","default_bg.png")
self.default_sound = os.path.join(self.config.pic_path,"silence.ogg") 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) self.update_ui(self.builder)
def show_configuration(self): def show_configuration(self, file_list):
self.builder = Gtk.Builder() self.builder = Gtk.Builder()
self.builder.set_translation_domain(self.config.gettext_domain) self.builder.set_translation_domain(self.config.gettext_domain)
self.file_list = file_list
self.refresh_static_data() 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. """ This method sets data that can't be changed from the dvd settings window.
It must be called before painting a menu """ It must be called before painting a menu """
if self.project.pal: if self.config.PAL:
self.y=576.0 self.y=576.0
else: else:
self.y=480.0 self.y=480.0
self.title_list = [] self.title_list = []
counter = 0 counter = 0
for element in self.project.get_all_files(): for element in self.file_list:
if element.show_in_menu: if element.show_in_menu:
self.title_list.append( (element, counter) ) self.title_list.append( (element, counter) )
counter += 1 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): def paint_menu(self,paint_background, paint_selected, paint_activated, page_number):
coordinates = []
if self.sf == None: if self.sf == None:
self.sf=cairo.ImageSurface(cairo.FORMAT_ARGB32,720,int(self.y)) self.sf=cairo.ImageSurface(cairo.FORMAT_ARGB32,720,int(self.y))
self.cr=cairo.Context(self.sf) self.cr=cairo.Context(self.sf)
@ -316,9 +319,9 @@ class dvd_menu(devede.interface_manager.interface_manager):
self.cr.restore() self.cr.restore()
hmargin = self.title_horizontal * 720.0 / 100.0 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") self.write_text(self.title_text, "title", 0 + hmargin, 720 + hmargin, self.title_vertical * self.y / 100.0, "center")
else: # else:
self.cr.set_source_rgb(1.0,1.0,1.0) # self.cr.set_source_rgb(1.0,1.0,1.0)
self.cr.paint() # self.cr.paint()
top_margin_p = self.y * self.margin_top / 100.0 top_margin_p = self.y * self.margin_top / 100.0
bottom_margin_p = self.y * self.margin_bottom / 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 xl = left_margin_p
xr = 720.0 - right_margin_p xr = 720.0 - right_margin_p
y = top_margin_p + entry_height/2.0 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]: 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 text = entry[0].title_name
if paint_background: if paint_background:
self.paint_base(xl, xr, y, 0) self.paint_base(xl, xr, y, 0)
@ -355,8 +360,10 @@ class dvd_menu(devede.interface_manager.interface_manager):
if paint_activated: if paint_activated:
self.write_text(text, "menu_entry_activated", xl, xr, y, self.position_horizontal) self.write_text(text, "menu_entry_activated", xl, xr, y, self.position_horizontal)
y += entry_height y += entry_height
if paint_arrows: if paint_arrows:
if page_number == 0: if page_number == 0:
coordinates.append([xl, y-height, xr, y+height, "right"])
if paint_background: if paint_background:
self.paint_base(xl, xr, y, 0) self.paint_base(xl, xr, y, 0)
self.paint_arrow(xl, xr, y, "menu_entry", False) self.paint_arrow(xl, xr, y, "menu_entry", False)
@ -365,6 +372,7 @@ class dvd_menu(devede.interface_manager.interface_manager):
if paint_activated: if paint_activated:
self.paint_arrow(xl, xr, y, "menu_entry_activated", False) self.paint_arrow(xl, xr, y, "menu_entry_activated", False)
elif page_number == (self.pages - 1): elif page_number == (self.pages - 1):
coordinates.append([xl, y-height, xr, y+height, "left"])
if paint_background: if paint_background:
self.paint_base(xl, xr, y, 0) self.paint_base(xl, xr, y, 0)
self.paint_arrow(xl, xr, y, "menu_entry", True) 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) self.paint_arrow(xl, xr, y, "menu_entry_activated", True)
else: else:
med = (xl + xr) / 2.0 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: if paint_background:
self.paint_base(xl, xr, y, 1) self.paint_base(xl, xr, y, 1)
self.paint_base(xl, xr, y, 2) self.paint_base(xl, xr, y, 2)
@ -385,6 +395,7 @@ class dvd_menu(devede.interface_manager.interface_manager):
if paint_activated: if paint_activated:
self.paint_arrow(med, xr, y, "menu_entry_activated", False) self.paint_arrow(med, xr, y, "menu_entry_activated", False)
self.paint_arrow(xl, med, y, "menu_entry_activated", True) self.paint_arrow(xl, med, y, "menu_entry_activated", True)
return coordinates
def paint_base(self,xl, xr, y, type_b): 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.set_source_surface(self.sf)
cr.paint() 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() self.refresh_static_data()
cv = devede.converter.converter() cv = devede.converter.converter()
menu_folder = os.path.join(base_path,"menu") 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() menu_converter = cv.get_menu_converter()
while n_page < self.pages: while n_page < self.pages:
self.sf = None 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.write_to_png(os.path.join(menu_folder,"menu_"+str(n_page)+"_bg.png"))
self.sf = None self.sf = None
self.paint_menu(False, False, False, n_page) self.paint_menu(False, False, False, n_page)
@ -461,9 +538,14 @@ class dvd_menu(devede.interface_manager.interface_manager):
self.sf = None self.sf = None
self.paint_menu(False, False, True, n_page) 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.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 = 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 # add this process without dependencies
processes.append([converter, None]) 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 n_page += 1
return processes return processes

View file

@ -33,11 +33,14 @@ class executor(GObject.GObject):
GObject.GObject.__init__(self) GObject.GObject.__init__(self)
self.config = devede.configuration_data.configuration.get_config() self.config = devede.configuration_data.configuration.get_config()
self.channel_stdin = None
self.channel_stdout = None self.channel_stdout = None
self.channel_stderr = None self.channel_stderr = None
self.text = "" self.text = ""
self.stdout_data = "" self.stdout_data = ""
self.stderr_data = "" self.stderr_data = ""
self.stdin_file = None
self.stdout_file = None
def run(self, progress_bar): def run(self, progress_bar):
@ -76,23 +79,60 @@ class executor(GObject.GObject):
def launch_process(self,command): def launch_process(self,command):
self.config.append_log("Launching:",False) self.launch_command = "Launching:"
for e in command: 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_stdout = GLib.IOChannel(self.handle.stdout.fileno())
self.channel_stderr = GLib.IOChannel(self.handle.stderr.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.channel_stderr.add_watch(GLib.IO_IN | GLib.IO_HUP,self.read_stderr)
self.stdout_buf = "" self.stdout_buf = ""
self.stderr_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): def read_stdout(self,source,condition):
if (condition != GLib.IO_IN): if (condition != GLib.IO_IN):
self.channel_stdout = None self.channel_stdout = None
if (self.channel_stderr == None): if ((self.channel_stderr == None) and (self.channel_stdin == None)):
self.wait_end() self.wait_end()
return False return False
else: else:
@ -109,11 +149,12 @@ class executor(GObject.GObject):
self.process_stdout(final_data) self.process_stdout(final_data)
return True return True
def read_stderr(self,source,condition): def read_stderr(self,source,condition):
if (condition != GLib.IO_IN): if (condition != GLib.IO_IN):
self.channel_stderr = None self.channel_stderr = None
if (self.channel_stdout == None): if ((self.channel_stdout == None) and (self.channel_stdin == None)):
self.wait_end() self.wait_end()
return False return False
else: else:
@ -142,6 +183,7 @@ class executor(GObject.GObject):
def wait_end(self): def wait_end(self):
self.config.append_log(self.text) 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.stdout_data)
self.config.append_log(self.stderr_data) self.config.append_log(self.stderr_data)
retval = self.handle.wait() 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.config = devede.configuration_data.configuration.get_config()
self.disc_type = self.config.disc_type 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 self.current_title = None
@ -252,7 +252,7 @@ class devede_project:
def on_menu_options_clicked(self,b): 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): def on_create_disc_clicked(self,b):
@ -262,6 +262,6 @@ class devede_project:
run_window = devede.runner.runner() 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.add_processes(p)
run_window.run() run_window.run()