From 86f77faa3f04a6f6b5906370ef6d9d542f9f8762 Mon Sep 17 00:00:00 2001 From: Sergio Costas Date: Wed, 23 Jul 2014 23:53:11 +0200 Subject: [PATCH] Now can launch one process per core, and launch new ones when the old ones end --- data/interface/wcreate.ui | 129 ++++++++++++++++++++++++++++++ data/interface/wmain.ui | 1 + data/interface/wprogress.ui | 68 ++++++++++++++++ src/devede/avconv_converter.py | 86 ++++++++++++++++++-- src/devede/configuration_data.py | 3 +- src/devede/converter.py | 12 ++- src/devede/create_disk_window.py | 64 +++++++++++++++ src/devede/dvd_menu.py | 78 ++++++++++++++---- src/devede/executor.py | 132 +++++++++++++++++++++++++++++-- src/devede/file_movie.py | 14 +++- src/devede/mplayer_detector.py | 96 ++++++++++++---------- src/devede/project.py | 23 +++++- src/devede/runner.py | 132 +++++++++++++++++++++++++++++++ 13 files changed, 761 insertions(+), 77 deletions(-) create mode 100644 data/interface/wcreate.ui create mode 100644 data/interface/wprogress.ui create mode 100644 src/devede/create_disk_window.py create mode 100644 src/devede/runner.py diff --git a/data/interface/wcreate.ui b/data/interface/wcreate.ui new file mode 100644 index 0000000..ee0b252 --- /dev/null +++ b/data/interface/wcreate.ui @@ -0,0 +1,129 @@ + + + + + + 380 + 270 + False + devede + devede.svg + dialog + + + False + vertical + 2 + + + False + end + + + gtk-cancel + True + True + True + True + + + False + True + 0 + + + + + gtk-ok + True + True + True + True + + + False + True + 1 + + + + + False + True + end + 0 + + + + + True + False + vertical + + + True + False + Choose the folder where Devede will create the files and a name for it. Do not use a folder in a VFAT/FAT32 drive. Characters /, | and \ are not accepted and will be replaced by underscores. + True + + + True + True + 0 + + + + + True + False + select-folder + + + + False + True + 1 + + + + + True + True + + + + False + True + 2 + + + + + Shutdown computer when disc is done + True + True + False + 0 + True + + + False + True + 3 + + + + + True + True + 1 + + + + + + button1 + accept + + + diff --git a/data/interface/wmain.ui b/data/interface/wmain.ui index a58c4b7..dea3c09 100644 --- a/data/interface/wmain.ui +++ b/data/interface/wmain.ui @@ -728,6 +728,7 @@ True True True + False diff --git a/data/interface/wprogress.ui b/data/interface/wprogress.ui new file mode 100644 index 0000000..1c5ea8e --- /dev/null +++ b/data/interface/wprogress.ui @@ -0,0 +1,68 @@ + + + + + + False + Creating... + False + center + devede.svg + False + False + + + True + False + vertical + + + True + False + 0 + none + + + + + + + + + False + True + 0 + + + + + True + False + True + + + False + True + 1 + + + + + gtk-cancel + True + True + True + True + + + + False + True + 8 + 2 + + + + + + diff --git a/src/devede/avconv_converter.py b/src/devede/avconv_converter.py index ba8271e..83337b5 100644 --- a/src/devede/avconv_converter.py +++ b/src/devede/avconv_converter.py @@ -17,14 +17,90 @@ # 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 +import devede.executor + +class avconv_converter(devede.executor.executor): + + supports_analize = False + supports_play = False + supports_convert = False + supports_menu = True + display_name = "AVCONV" + + @staticmethod + def check_is_installed(): + handle = subprocess.Popen(["avconv","-version"], stdout = subprocess.PIPE, stderr = subprocess.PIPE) + (stdout, stderr) = handle.communicate() + if 0==handle.wait(): + return True + else: + return False -class avconv_converter: - def __init__(self): - + + devede.executor.executor.__init__(self) self.config = devede.configuration_data.configuration.get_config() - \ No newline at end of file + def create_mpg(self,n_page,background_music,sound_length,pal,output_path): + + self.n_page = n_page + self.sound_length = float(sound_length) + self.text = _("Creating menu %(X)d") % {"X": self.n_page} + + self.command_var=[] + self.command_var.append("avconv") + + self.command_var.append("-loop") + self.command_var.append("1") + + self.command_var.append("-f") + self.command_var.append("image2") + self.command_var.append("-i") + self.command_var.append(os.path.join(output_path,"menu_"+str(n_page)+"_bg.png")) + self.command_var.append("-i") + self.command_var.append(background_music) + + self.command_var.append("-y") + self.command_var.append("-target") + if pal: + self.command_var.append("pal-dvd") + else: + self.command_var.append("ntsc-dvd") + self.command_var.append("-acodec") + self.command_var.append("mp2") + self.command_var.append("-s") + if pal: + self.command_var.append("720x576") + else: + self.command_var.append("720x480") + self.command_var.append("-g") + self.command_var.append("12") + self.command_var.append("-b:v") + self.command_var.append("2500k") + self.command_var.append("-b:a") + self.command_var.append("192k") + self.command_var.append("-aspect") + self.command_var.append("4:3") + + self.command_var.append("-t") + self.command_var.append(str(1+sound_length)) + + self.command_var.append(os.path.join(output_path,"menu_"+str(n_page)+".mpg")) + + def process_stdout(self,data): + + pass + + def process_stderr(self,data): + + 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/configuration_data.py b/src/devede/configuration_data.py index 5b2cfe1..abb7033 100644 --- a/src/devede/configuration_data.py +++ b/src/devede/configuration_data.py @@ -33,6 +33,7 @@ class configuration(GObject.GObject): configuration.current_configuration = None return configuration.current_configuration + def fill_config(self): GObject.GObject.__init__(self) @@ -78,7 +79,7 @@ class configuration(GObject.GObject): self.PAL = True self.tmp_folder = "/var/tmp" self.multicore = True - self.final_folder = None + self.final_folder = os.environ.get("HOME") self.sub_language = None self.sub_codepage = None self.film_analizer = None diff --git a/src/devede/converter.py b/src/devede/converter.py index 18dc7e9..e06a496 100644 --- a/src/devede/converter.py +++ b/src/devede/converter.py @@ -17,6 +17,7 @@ import devede.configuration_data import devede.mplayer_detector +import devede.avconv_converter class converter: @@ -32,7 +33,8 @@ class converter: def __init__(self): self.config = devede.configuration_data.configuration.get_config() - self.c = [devede.mplayer_detector.mplayer_detector] + # List of classes with conversion capabilities, in order of preference + self.c = [devede.mplayer_detector.mplayer_detector, devede.avconv_converter.avconv_converter] self.analizers = {} self.default_analizer = None @@ -111,3 +113,11 @@ class converter: return self.default_analizer else: return self.analizers[self.config.film_analizer] + + def get_menu_converter(self): + """ returns a class for the desired menu converter, or the most priviledged if the desired is not installed """ + + if (self.config.menu_converter == None) or (self.analizers.has_key(self.config.menu_converter) == False): + return self.default_menuer + else: + return self.menuers[self.config.menu_converter] \ No newline at end of file diff --git a/src/devede/create_disk_window.py b/src/devede/create_disk_window.py new file mode 100644 index 0000000..40f9d3a --- /dev/null +++ b/src/devede/create_disk_window.py @@ -0,0 +1,64 @@ +# 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 + +from gi.repository import Gtk +import os +import devede.configuration_data + +class create_disk_window: + + def __init__(self): + + self.config = devede.configuration_data.configuration.get_config() + + def run(self): + + builder = Gtk.Builder() + builder.set_translation_domain(self.config.gettext_domain) + + builder.add_from_file(os.path.join(self.config.glade,"wcreate.ui")) + builder.connect_signals(self) + wcreate_window = builder.get_object("dialog_create") + self.wpath = builder.get_object("path") + self.wname = builder.get_object("name") + wshutdown = builder.get_object("shutdown") + self.waccept = builder.get_object("accept") + + self.wname.set_text("movie") + self.wpath.set_current_folder(self.config.final_folder) + + wcreate_window.show_all() + self.on_iface_changed(None) + retval = wcreate_window.run() + self.path = self.wpath.get_current_folder() + self.name = self.wname.get_text() + self.shutdown = wshutdown.get_active() + wcreate_window.destroy() + if (retval == 1): + return True + else: + return False + + def on_iface_changed(self,b): + + path = self.wpath.get_current_folder() + name = self.wname.get_text() + + if ((path == None) or (path == "") or (name == None) or (name == "")): + self.waccept.set_sensitive(False) + else: + self.waccept.set_sensitive(True) \ No newline at end of file diff --git a/src/devede/dvd_menu.py b/src/devede/dvd_menu.py index bea3a4b..de7256d 100644 --- a/src/devede/dvd_menu.py +++ b/src/devede/dvd_menu.py @@ -20,6 +20,7 @@ from gi.repository import Gtk,Gdk,GdkPixbuf import os import devede.configuration_data import devede.interface_manager +import devede.message class dvd_menu(devede.interface_manager.interface_manager): @@ -59,12 +60,28 @@ class dvd_menu(devede.interface_manager.interface_manager): self.add_fontbutton("entry_font", "Sans 18", self.update_preview) self.add_filebutton("background_picture", self.default_background, self.update_preview) - self.add_filebutton("background_music", self.default_sound, self.update_preview) + self.add_filebutton("background_music", self.default_sound, self.update_music) self.cached_menu_font = None self.cached_menu_size = 0 + self.sound_length = 30 + def update_music(self,b=None): + + self.store_ui(self.builder) + cv = devede.converter.converter() + film_analizer = (cv.get_film_analizer())() + (video, audio, length) = film_analizer.analize_film_data(self.background_music,True) + if (video != 0): + devede.message.message_window(_("The selected file is a video, not an audio file"),_("Error")) + self.on_no_sound_clicked(None) + elif (audio == 0): + devede.message.message_window(_("The selected file is not an audio file"),_("Error")) + self.on_no_sound_clicked(None) + else: + self.sound_length = length + def update_preview(self,b=None): self.store_ui(self.builder) @@ -80,6 +97,7 @@ class dvd_menu(devede.interface_manager.interface_manager): def on_no_sound_clicked(self,b): self.background_music = self.default_sound + self.sound_length = 30 self.update_ui(self.builder) @@ -118,10 +136,6 @@ class dvd_menu(devede.interface_manager.interface_manager): self.wmenu.destroy() - def on_preview_menu_clicked(self,b): - pass - - def get_font_params(self,font_name): font_elements=font_name.split(" ") @@ -161,7 +175,7 @@ class dvd_menu(devede.interface_manager.interface_manager): elif arrow_type == "menu_entry_selected": fgcolor = self.selected_color elif arrow_type == "menu_entry_activated": - fgcolor = ( 1.0 - self.selected_color[0], 1.0 - self.selected_color[1], 1.0 - self.selected_color[2] ) + fgcolor = ( 1.0 - self.selected_color[0], 1.0 - self.selected_color[1], 1.0 - self.selected_color[2], self.selected_color[3]) else: return @@ -210,7 +224,7 @@ class dvd_menu(devede.interface_manager.interface_manager): hard_borders = True font = self.entry_font elif text_type == "menu_entry_activated": - fgcolor = ( 1.0 - self.selected_color[0], 1.0 - self.selected_color[1], 1.0 - self.selected_color[2] ) + fgcolor = ( 1.0 - self.selected_color[0], 1.0 - self.selected_color[1], 1.0 - self.selected_color[2], self.selected_color[3]) bgcolor = None hard_borders = True font = self.entry_font @@ -256,7 +270,7 @@ 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.config.PAL: + if self.project.pal: self.y=576.0 else: self.y=480.0 @@ -270,6 +284,7 @@ class dvd_menu(devede.interface_manager.interface_manager): self.sf = None self.current_shown_page = 0 + self.wcurrent_page = None def paint_menu(self,paint_background, paint_selected, paint_activated, page_number): @@ -325,7 +340,8 @@ class dvd_menu(devede.interface_manager.interface_manager): if (page_number >= self.pages) and (page_number > 0): page_number -= 1 - self.wcurrent_page.set_text(_("Page %(X)d of %(Y)d") % {"X":page_number+1 , "Y":self.pages}) + if self.wcurrent_page != None: + self.wcurrent_page.set_text(_("Page %(X)d of %(Y)d") % {"X":page_number+1 , "Y":self.pages}) xl = left_margin_p xr = 720.0 - right_margin_p y = top_margin_p + entry_height/2.0 @@ -341,26 +357,26 @@ class dvd_menu(devede.interface_manager.interface_manager): y += entry_height if paint_arrows: if page_number == 0: - self.paint_base(xl, xr, y, 0) if paint_background: + self.paint_base(xl, xr, y, 0) self.paint_arrow(xl, xr, y, "menu_entry", False) if paint_selected: self.paint_arrow(xl, xr, y, "menu_entry_selected", False) if paint_activated: self.paint_arrow(xl, xr, y, "menu_entry_activated", False) elif page_number == (self.pages - 1): - self.paint_base(xl, xr, y, 0) if paint_background: + self.paint_base(xl, xr, y, 0) self.paint_arrow(xl, xr, y, "menu_entry", True) if paint_selected: self.paint_arrow(xl, xr, y, "menu_entry_selected", True) if paint_activated: self.paint_arrow(xl, xr, y, "menu_entry_activated", True) else: - self.paint_base(xl, xr, y, 1) - self.paint_base(xl, xr, y, 2) med = (xl + xr) / 2.0 if paint_background: + self.paint_base(xl, xr, y, 1) + self.paint_base(xl, xr, y, 2) self.paint_arrow(med, xr, y, "menu_entry", False) self.paint_arrow(xl, med, y, "menu_entry", True) if paint_selected: @@ -411,9 +427,6 @@ class dvd_menu(devede.interface_manager.interface_manager): """ Callback to repaint the menu preview window when it sends the EXPOSE event """ - if not self.config.menu_dynamic_preview: - return - if (self.sf == None): self.paint_menu(True, self.wshow_as_selected.get_active(), False, self.current_shown_page) if (self.current_shown_page >= self.pages): @@ -421,3 +434,36 @@ class dvd_menu(devede.interface_manager.interface_manager): cr.set_source_surface(self.sf) cr.paint() + + def create_dvd_menus(self,base_path): + + self.refresh_static_data() + cv = devede.converter.converter() + menu_folder = os.path.join(base_path,"menu") + try: + os.makedirs(menu_folder) + except: + pass + n_page = 0 + self.pages = 1 + processes = [] + menu_converter = cv.get_menu_converter() + while n_page < self.pages: + self.sf = None + 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) + self.sf.write_to_png(os.path.join(menu_folder,"menu_"+str(n_page)+"_unselected_bg.png")) + self.sf = None + self.paint_menu(False, True, False, n_page) + self.sf.write_to_png(os.path.join(menu_folder,"menu_"+str(n_page)+"_selected_bg.png")) + 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")) + converter = menu_converter() + converter.create_mpg(n_page,self.background_music,self.sound_length,self.project.pal,menu_folder) + # add this process without dependencies + processes.append([converter, None]) + n_page += 1 + return processes \ No newline at end of file diff --git a/src/devede/executor.py b/src/devede/executor.py index e388f58..5d3b4be 100644 --- a/src/devede/executor.py +++ b/src/devede/executor.py @@ -17,16 +17,132 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see +from gi.repository import GLib,GObject import subprocess - +import os +import signal import devede.configuration_data -class executor: +class executor(GObject.GObject): """ This class encapsulates everything needed for launching processes """ - - def __init__(self): - - self.config = devede.configuration_data.configuration.get_config() - - \ No newline at end of file + __gsignals__ = {'ended': (GObject.SIGNAL_RUN_FIRST, None,(int,))} + + def __init__(self): + + GObject.GObject.__init__(self) + + self.config = devede.configuration_data.configuration.get_config() + self.channel_stdout = None + self.channel_stderr = None + self.text = "" + self.stdout_data = "" + self.stderr_data = "" + + def run(self, progress_bar): + + self.progress_bar = progress_bar + self.launch_process(self.command_var) + self.progress_bar[0].set_label(self.text) + self.progress_bar[1].set_fraction(0.0) + self.progress_bar[0].show_all() + + def remove_ansi(self,line): + + output="" + while True: + pos=line.find("\033[") # try with double-byte ESC + jump=2 + if pos==-1: + pos=line.find("\233") # if not, try with single-byte ESC + jump=1 + 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 + if (ord(line[0])<64) or (ord(line[0])>126): + line=line[1:] + else: + line=line[1:] + break + return output + + + def launch_process(self,command): + + self.config.append_log("Launching:",False) + for e in command: + self.config.append_log(e+" ") + + 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) + self.channel_stderr.add_watch(GLib.IO_IN | GLib.IO_HUP,self.read_stderr) + self.stdout_buf = "" + self.stderr_buf = "" + + def read_stdout(self,source,condition): + + if (condition != GLib.IO_IN): + self.channel_stdout = None + if (self.channel_stderr == None): + self.wait_end() + return False + else: + line_data = self.stdout_buf+(self.handle.stdout.read1(4096).decode("utf-8")) + self.stdout_data += line_data + data = (line_data).replace("\r","\n").split("\n") + if (len(data) == 1): + final_data = [] + self.stdout_buf = data[0] + else: + final_data = data[:-1] + self.stdout_buf = data[-1] + if (len(final_data) != 0): + 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): + self.wait_end() + return False + else: + line_data = self.stderr_buf+(self.handle.stderr.read1(4096).decode("utf-8")) + self.stderr_data += line_data + data = (line_data).replace("\r","\n").split("\n") + if (len(data) == 1): + final_data = [] + self.stderr_buf = data[0] + else: + final_data = data[:-1] + self.stderr_buf = data[-1] + if (len(final_data) != 0): + self.process_stderr(final_data) + return True + + def cancel(self): + + """ Called to kill this process. """ + + if self.handle==None: + return + os.kill(self.handle.pid,signal.SIGKILL) + + + def wait_end(self): + + self.config.append_log(self.text) + self.config.append_log(self.stdout_data) + self.config.append_log(self.stderr_data) + retval = self.handle.wait() + self.emit("ended",retval) \ No newline at end of file diff --git a/src/devede/file_movie.py b/src/devede/file_movie.py index 07a989b..5bc20b6 100644 --- a/src/devede/file_movie.py +++ b/src/devede/file_movie.py @@ -116,9 +116,21 @@ class file_movie(devede.interface_manager.interface_manager): cv = devede.converter.converter() film_analizer = (cv.get_film_analizer())() - if (film_analizer.get_film_data(self)): + if (film_analizer.get_film_data(self.file_name)): self.error = True else: + self.audio_list = film_analizer.audio_list + self.audio_streams = film_analizer.audio_streams + self.video_streams = film_analizer.video_streams + self.original_width = film_analizer.original_width + self.original_height = film_analizer.original_height + self.original_length = film_analizer.original_length + self.original_size = film_analizer.original_size + self.original_aspect_ratio = film_analizer.original_aspect_ratio + self.original_videorate = film_analizer.original_videorate + self.original_audiorate = film_analizer.original_audiorate + self.original_audiorate_uncompressed = film_analizer.original_audiorate_uncompressed + self.original_fps = film_analizer.original_fps self.error = False diff --git a/src/devede/mplayer_detector.py b/src/devede/mplayer_detector.py index 9ef736f..d61f54f 100644 --- a/src/devede/mplayer_detector.py +++ b/src/devede/mplayer_detector.py @@ -17,8 +17,9 @@ import subprocess import devede.configuration_data +import devede.executor -class mplayer_detector: +class mplayer_detector(devede.executor.executor): supports_analize = True supports_play = True @@ -39,81 +40,92 @@ class mplayer_detector: self.config = devede.configuration_data.configuration.get_config() - def get_film_data(self,movie): + def get_film_data(self, file_name): """ processes a file, refered by the FILE_MOVIE movie object, and fills its main data (resolution, FPS, length...) """ - video = self.get_film_data2(movie, True) + (video, audio, length) = self.analize_film_data(file_name, True) - if (video): - self.get_film_data2(movie, False) + if (video != 0): + self.analize_film_data(file_name, False) return False # no error else: return True # the file is not a video file; maybe an audio-only file, or another thing - def get_film_data2(self,movie,check_audio): + def analize_film_data(self,file_name,check_audio): if (check_audio): frames = "0" else: frames = "1" - command_line = ["mplayer","-loop","1","-identify", "-vo", "null", "-ao", "null", "-frames", frames , movie.file_name] + command_line = ["mplayer","-loop","1","-identify", "-vo", "null", "-ao", "null", "-frames", frames , file_name] handle = subprocess.Popen(command_line, stdout = subprocess.PIPE, stderr = subprocess.PIPE) (stdout, stderr) = handle.communicate() minimum_audio=-1 - movie.audio_list=[] - movie.audio_streams = 0 - movie.video_streams = 0 - movie.original_width = 0 - movie.original_height = 0 + self.audio_list=[] + self.audio_streams = 0 + self.video_streams = 0 + self.original_width = 0 + self.original_height = 0 + self.original_length = 0 + self.original_videorate = 0 + self.original_audiorate = 0 + self.original_audiorate_uncompressed = 0 + self.original_fps = 0 for line in str(stdout).split("\\n"): - #line=self.remove_ansi(line) + line=self.remove_ansi(line) if line == "": continue position=line.find("ID_") if position==-1: continue line=line[position:] - if (not check_audio): - if line[:16]=="ID_VIDEO_BITRATE": - movie.original_videorate=int(int(line[17:])/1000) - if line[:14]=="ID_VIDEO_WIDTH": - movie.original_width=int(line[15:]) - if line[:15]=="ID_VIDEO_HEIGHT": - movie.original_height=int(line[16:]) - if line[:15]=="ID_VIDEO_ASPECT": - movie.original_aspect_ratio=float(line[16:]) - if line[:12]=="ID_VIDEO_FPS": - movie.original_fps=float(line[13:]) - if line[:16]=="ID_AUDIO_BITRATE": - movie.original_audiorate=int(int(line[17:])/1000) - if line[:13]=="ID_AUDIO_RATE": - movie.original_audiorate_uncompressed=int(line[14:]) - if line[:9]=="ID_LENGTH": - movie.original_length=int(float(line[10:])) + + if line[:16]=="ID_VIDEO_BITRATE": + self.original_videorate=int(int(line[17:])/1000) + if line[:14]=="ID_VIDEO_WIDTH": + self.original_width=int(line[15:]) + if line[:15]=="ID_VIDEO_HEIGHT": + self.original_height=int(line[16:]) + if line[:15]=="ID_VIDEO_ASPECT": + self.original_aspect_ratio=float(line[16:]) + if line[:12]=="ID_VIDEO_FPS": + self.original_fps=float(line[13:]) + if line[:16]=="ID_AUDIO_BITRATE": + self.original_audiorate=int(int(line[17:])/1000) + if line[:13]=="ID_AUDIO_RATE": + self.original_audiorate_uncompressed=int(line[14:]) + if line[:9]=="ID_LENGTH": + self.original_length=int(float(line[10:])) if line[:11]=="ID_VIDEO_ID": - movie.video_streams+=1 + self.video_streams+=1 if line[:11]=="ID_AUDIO_ID": - movie.audio_streams+=1 + self.audio_streams+=1 audio_track=int(line[12:]) if (minimum_audio == -1) or (minimum_audio>audio_track): minimum_audio=audio_track - movie.audio_list.append(audio_track) + self.audio_list.append(audio_track) - movie.original_size = str(movie.original_width)+"x"+str(movie.original_height) - if (movie.original_aspect_ratio == None) or (movie.original_aspect_ratio <= 1.0): - if (movie.original_height != 0): - movie.original_aspect_ratio = (float(movie.original_width))/(float(movie.original_height)) + if (check_audio): - if (movie.original_aspect_ratio != None): - movie.original_aspect_ratio = (float(int(movie.original_aspect_ratio*1000.0)))/1000.0 + return (self.video_streams, self.audio_streams, self.original_length) - if (movie.video_streams == 0): - return False else: - return True \ No newline at end of file + + self.original_size = str(self.original_width)+"x"+str(self.original_height) + if (self.original_aspect_ratio == None) or (self.original_aspect_ratio <= 1.0): + if (self.original_height != 0): + self.original_aspect_ratio = (float(self.original_width))/(float(self.original_height)) + + if (self.original_aspect_ratio != None): + self.original_aspect_ratio = (float(int(self.original_aspect_ratio*1000.0)))/1000.0 + + if (self.video_streams == 0): + return False + else: + return True \ No newline at end of file diff --git a/src/devede/project.py b/src/devede/project.py index 0874221..c3217d8 100644 --- a/src/devede/project.py +++ b/src/devede/project.py @@ -23,6 +23,8 @@ import devede.ask import devede.add_files import devede.message import devede.dvd_menu +import devede.create_disk_window +import devede.runner class devede_project: @@ -70,8 +72,10 @@ class devede_project: if (self.config.PAL): self.wuse_pal.set_active(True) + self.pal = True else: self.wuse_ntsc.set_active(True) + self.pal = False self.wcreate_menu.set_active(True) @@ -140,11 +144,11 @@ class devede_project: self.wproperties_file.set_sensitive(True) self.wpreview_file.set_sensitive(True) - self.config.PAL = self.wuse_pal.get_active() - status = self.wcreate_menu.get_active() self.wmenu_options.set_sensitive(status) + self.pal = self.wuse_pal.get_active() + (element, position, model, treeiter) = self.get_current_file() if (element == None): self.wdelete_file.set_sensitive(False) @@ -164,6 +168,7 @@ class devede_project: def on_use_pal_toggled(self,b): + self.config.PAL = self.wuse_pal.get_active() self.set_interface_status(None) @@ -247,4 +252,16 @@ class devede_project: def on_menu_options_clicked(self,b): - self.menu.show_configuration() \ No newline at end of file + self.menu.show_configuration() + + def on_create_disc_clicked(self,b): + + data = devede.create_disk_window.create_disk_window() + if (not data.run()): + return + + run_window = devede.runner.runner() + + p = self.menu.create_dvd_menus(data.path) + run_window.add_processes(p) + run_window.run() \ No newline at end of file diff --git a/src/devede/runner.py b/src/devede/runner.py new file mode 100644 index 0000000..52237e5 --- /dev/null +++ b/src/devede/runner.py @@ -0,0 +1,132 @@ +# 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 + +from gi.repository import Gtk,GObject +import os +import devede.configuration_data + +class runner(GObject.GObject): + + def __init__(self): + + self.config = devede.configuration_data.configuration.get_config() + if (self.config.multicore): + self.count_cores() + else: + self.cores = 1 + + self.proc_list = [] + self.running = 0 + + self.builder = Gtk.Builder() + self.builder.set_translation_domain(self.config.gettext_domain) + + self.builder.add_from_file(os.path.join(self.config.glade,"wprogress.ui")) + self.builder.connect_signals(self) + self.wprogress = self.builder.get_object("progress") + self.wprogress.show_all() + self.wtotal = self.builder.get_object("progress_total") + + progress_frame = self.builder.get_object("progress_frame") + box = Gtk.Box(Gtk.Orientation.VERTICAL, 0) + progress_frame.add(box) + box.show() + self.progress_bars = [] + self.used_progress_bars = [] + for c in range(0,self.cores): + f = Gtk.Frame() + p = Gtk.ProgressBar() + p.set_orientation(Gtk.Orientation.HORIZONTAL) + f.add(p) + # A frame, a progress bar, and the process running in that bar + self.progress_bars.append([f, p, None]) + box.pack_start(f,True,True,0) + box.set_orientation(Gtk.Orientation.VERTICAL) + self.total = 0 + + def add_processes(self,processes): + for p in processes: + p.append(None) # this will contain the progress bar being used by this process + self.proc_list.append(p) + self.total_processes = len(self.proc_list) + + + def on_cancel_clicked(self,b): + pass + + def count_cores(self): + + self.cores = 0 + proc_file = open("/proc/cpuinfo","r") + for line in proc_file: + if (line.startswith("processor")): + self.cores += 1 + + def run(self): + + for element in self.proc_list: + # each element has three items: + # * the process object + # * the list of dependencies, or None if there are no more dependencies + # * the progress bar being used by this process + if (element[1] == None) and (element[2] == None): + self.progress_bars[0][2] = element[0] + element[0].connect("ended",self.process_ended) + element[0].run(self.progress_bars[0]) + element[2] = self.progress_bars[0] + self.used_progress_bars.append(self.progress_bars[0]) + if (len(self.progress_bars) > 1): + self.progress_bars = self.progress_bars[1:] + else: + self.progress_bars = [] + break + self.wtotal.set_text(str(len(self.proc_list)-self.total)+"/"+str(self.total)) + + def process_ended(self,process, retval): + + # move the progress bar used by this process to the list of available progress bars + tmp = [] + for e in self.used_progress_bars: + if (e[2] == process): + e[2] = None + self.progress_bars.append(e) + e[0].hide() + else: + tmp.append(e) + self.used_progress_bars = tmp + + # remove this process from the list of processes, and remove it from the dependencies in other processes + tmp = [] + for e in self.proc_list: + if (e[0] != process): + tmp.append(e) + if (e[1] != None): + tmp2 = [] + for dep in e[1]: + if dep != process: + tmp2.append(dep) + if (len(tmp2) != 0): + e[1] = tmp2 + else: + e[1] = None + self.proc_list = tmp + + # launch a new process + if (len(self.proc_list) != 0): + self.run() + else: + self.wprogress.destroy() \ No newline at end of file