From e404f27e4573a3a32f15a0a7f11f322602d41215 Mon Sep 17 00:00:00 2001 From: Sergio Costas Date: Thu, 24 Jul 2014 20:49:23 +0200 Subject: [PATCH] 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 --- data/interface/wprogress.ui | 1 + src/devede/avconv_converter.py | 1 - src/devede/create_disk_window.py | 2 + src/devede/dvd_menu.py | 104 +++++++++++++++++++++++++++---- src/devede/executor.py | 60 +++++++++++++++--- src/devede/mux_dvd_menu.py | 54 ++++++++++++++++ src/devede/project.py | 6 +- 7 files changed, 204 insertions(+), 24 deletions(-) create mode 100644 src/devede/mux_dvd_menu.py diff --git a/data/interface/wprogress.ui b/data/interface/wprogress.ui index 1c5ea8e..22a3eba 100644 --- a/data/interface/wprogress.ui +++ b/data/interface/wprogress.ui @@ -6,6 +6,7 @@ False Creating... False + True center devede.svg False diff --git a/src/devede/avconv_converter.py b/src/devede/avconv_converter.py index 83337b5..8db4a35 100644 --- a/src/devede/avconv_converter.py +++ b/src/devede/avconv_converter.py @@ -17,7 +17,6 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see -from gi.repository import GLib import subprocess import os import devede.configuration_data diff --git a/src/devede/create_disk_window.py b/src/devede/create_disk_window.py index 40f9d3a..0485363 100644 --- a/src/devede/create_disk_window.py +++ b/src/devede/create_disk_window.py @@ -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 diff --git a/src/devede/dvd_menu.py b/src/devede/dvd_menu.py index de7256d..3e2cca1 100644 --- a/src/devede/dvd_menu.py +++ b/src/devede/dvd_menu.py @@ -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('\n\t\n\t\t\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\n') + counter += 1 + + xml_file.write("\n\n\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 \ No newline at end of file diff --git a/src/devede/executor.py b/src/devede/executor.py index 5d3b4be..392bd8f 100644 --- a/src/devede/executor.py +++ b/src/devede/executor.py @@ -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() diff --git a/src/devede/mux_dvd_menu.py b/src/devede/mux_dvd_menu.py new file mode 100644 index 0000000..7417b0a --- /dev/null +++ b/src/devede/mux_dvd_menu.py @@ -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 + +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) \ No newline at end of file diff --git a/src/devede/project.py b/src/devede/project.py index c3217d8..dbee950 100644 --- a/src/devede/project.py +++ b/src/devede/project.py @@ -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() \ No newline at end of file