diff --git a/data/interface/wfile_properties.ui b/data/interface/wfile_properties.ui
index 9b1dfac..54ab0c9 100644
--- a/data/interface/wfile_properties.ui
+++ b/data/interface/wfile_properties.ui
@@ -2,47 +2,56 @@
-
diff --git a/data/interface/wselect_disk.ui b/data/interface/wselect_disk.ui
index e983b60..5a24485 100644
--- a/data/interface/wselect_disk.ui
+++ b/data/interface/wselect_disk.ui
@@ -4,9 +4,12 @@
False
+ False
+ Truecenterdevede.svg
-
+ False
+ FalseTrue
@@ -261,6 +264,53 @@ Creates files compliant with DivX home players
5
+
+
+ True
+ True
+ True
+
+
+
+ True
+ False
+
+
+ True
+ False
+ icon_mkv.png
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ 0
+ <b>Matroska / H.264</b>
+Creates H.264 files in a MKV container
+ True
+
+
+ True
+ True
+ 4
+ 1
+
+
+
+
+
+
+ True
+ True
+ 6
+
+
diff --git a/data/pixmaps/icon_mkv.png b/data/pixmaps/icon_mkv.png
new file mode 100644
index 0000000..ec95f6c
Binary files /dev/null and b/data/pixmaps/icon_mkv.png differ
diff --git a/src/devede/add_files.py b/src/devede/add_files.py
index 3339d73..83f7b9b 100644
--- a/src/devede/add_files.py
+++ b/src/devede/add_files.py
@@ -26,14 +26,6 @@ class add_files:
def __init__(self):
self.config = devede.configuration_data.configuration.get_config()
- self.show_title_options = True
-
- def set_type(self,disc_type):
-
- if (disc_type == "dvd"):
- self.show_title_options = True
- else:
- self.show_title_options = False
def run(self):
diff --git a/src/devede/convert.py b/src/devede/avconv_converter.py
similarity index 75%
rename from src/devede/convert.py
rename to src/devede/avconv_converter.py
index 5ce867c..ba8271e 100644
--- a/src/devede/convert.py
+++ b/src/devede/avconv_converter.py
@@ -1,3 +1,5 @@
+#!/usr/bin/env python3
+
# Copyright 2014 (C) Raster Software Vigo (Sergio Costas)
#
# This file is part of DeVeDe-NG
@@ -15,5 +17,14 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see
-def test():
- print("Test function2")
\ No newline at end of file
+import subprocess
+
+import devede.configuration_data
+
+class avconv_converter:
+
+ def __init__(self):
+
+ self.config = devede.configuration_data.configuration.get_config()
+
+
\ No newline at end of file
diff --git a/src/devede/check_binaries.py b/src/devede/check_binaries.py
new file mode 100644
index 0000000..f31586c
--- /dev/null
+++ b/src/devede/check_binaries.py
@@ -0,0 +1,48 @@
+#!/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 subprocess
+
+import devede.configuration_data
+
+class check_binaries:
+
+ def __init__(self):
+
+ self.config = devede.configuration_data.configuration.get_config()
+
+ self.check_mplayer()
+ self.check_mpv()
+
+
+ def check_mplayer(self):
+
+ handle = subprocess.Popen(["mplayer","-v"])
+ if 0==handle.wait():
+ self.config.mplayer_available = True
+ else:
+ self.config.mplayer_available = False
+
+ def check_mpv(self):
+
+ handle = subprocess.Popen(["mpv","-v"])
+ if 0==handle.wait():
+ self.config.mpv_available = True
+ else:
+ self.config.mpv_available = False
\ No newline at end of file
diff --git a/src/devede/choose_disc_type.py b/src/devede/choose_disc_type.py
new file mode 100644
index 0000000..ad426f2
--- /dev/null
+++ b/src/devede/choose_disc_type.py
@@ -0,0 +1,66 @@
+# 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 choose_disc_type(GObject.GObject):
+
+ def __init__(self):
+
+ self.config = devede.configuration_data.configuration.get_config()
+
+ builder = Gtk.Builder()
+ builder.set_translation_domain(self.config.gettext_domain)
+
+ builder.add_from_file(os.path.join(self.config.glade,"wselect_disk.ui"))
+ builder.connect_signals(self)
+ self.wask_window = builder.get_object("wselect_disk")
+ self.wask_window.show_all()
+
+ def set_type(self,disc_type):
+
+ self.config.set_disc_type(disc_type)
+ self.wask_window.hide()
+ self.wask_window.destroy()
+ self.wask_window = None
+
+ def on_button_dvd_clicked(self,b):
+
+ self.set_type("dvd")
+
+ def on_button_vcd_clicked(self,b):
+
+ self.set_type("vcd")
+
+ def on_button_svcd_clicked(self,b):
+
+ self.set_type("svcd")
+
+ def on_button_cvd_clicked(self,b):
+
+ self.set_type("cvd")
+
+ def on_button_divx_clicked(self,b):
+
+ self.set_type("divx")
+
+ def on_button_mkv_clicked(self,b):
+
+ self.set_type("mkv")
diff --git a/src/devede/configuration_data.py b/src/devede/configuration_data.py
index 3aacb1b..2904ab9 100644
--- a/src/devede/configuration_data.py
+++ b/src/devede/configuration_data.py
@@ -17,38 +17,45 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see
+from gi.repository import GObject
import os
-class configuration:
+class configuration(GObject.GObject):
current_configuration = None
+ __gsignals__ = {'disc_type': (GObject.SIGNAL_RUN_FIRST, None,(str,))}
@staticmethod
def get_config():
if configuration.current_configuration == None:
configuration.current_configuration = configuration()
+ if (configuration.current_configuration.fill_config()):
+ configuration.current_configuration = None
return configuration.current_configuration
- def __init__(self):
+ def fill_config(self):
+
+ GObject.GObject.__init__(self)
- self.error = False
is_local = None
+ self.log = ""
+ self.disc_type = None
try:
os.stat("/usr/share/devede_ng/wselect_disk.ui")
is_local = False
except:
pass
-
+
if is_local == None:
try:
os.stat("/usr/local/share/devede_ng/wselect_disk.ui")
is_local = True
except:
pass
-
+
if is_local == None:
- self.error = True
+ return True
else:
if (is_local):
# locales must be always at /usr/share/locale because Gtk.Builder always search there
@@ -74,6 +81,11 @@ class configuration:
self.final_folder = None
self.sub_language = None
self.sub_codepage = None
+ self.film_analizer = None
+ self.film_player = None
+ self.film_converter = None
+ self.menu_converter = None
+ self.subtitles_font_size = 28
config_path = os.path.join(os.environ.get("HOME"),".devede")
try:
@@ -87,29 +99,54 @@ class configuration:
if linea[:13]=="video_format:":
if linea[13:].strip() =="pal":
self.PAL=True
- continue
- if linea[13:].strip()=="ntsc":
+ elif linea[13:].strip()=="ntsc":
self.PAL=False
- continue
+ continue
if linea[:12]=="temp_folder:":
self.tmp_folder=linea[12:].strip()
+ continue
if linea[:10]=="multicore:":
if linea[10:].strip()=="1":
self.multicore = False
else:
self.multicore = True
+ continue
if linea[:13]=="final_folder:":
self.final_folder=linea[13:].strip()
+ continue
if linea[:13]=="sub_language:":
self.sub_language=linea[13:].strip()
+ continue
if linea[:13]=="sub_codepage:":
self.sub_codepage=linea[13:].strip()
+ continue
+ if linea[:14]=="film_analizer:":
+ self.film_analizer = linea[14:].strip()
+ continue
+ if linea[:12]=="film_player:":
+ self.film_player = linea[12:].strip()
+ continue
+ if linea[:15]=="film_converter:":
+ self.film_converter = linea[15:].strip()
+ continue
+ if linea[:15]=="menu_converter:":
+ self.menu_converter = linea[15:].strip()
+ continue
+ if linea[:19]=="subtitle_font_size:":
+ self.subtitles_font_size = int(linea[19:].strip())
config_data.close()
except:
pass
-
+
+ return False
+
+ def set_disc_type(self,disc_type):
+
+ self.disc_type = disc_type
+ self.emit('disc_type',disc_type)
+
def save_config(self):
-
+
config_path = os.path.join(os.environ.get("HOME"),".devede")
try:
config_data = open(config_path,"w")
@@ -131,6 +168,29 @@ class configuration:
config_data.write("sub_language:"+str(self.sub_language)+"\n")
if (self.sub_codepage != None):
config_data.write("sub_codepage:"+str(self.sub_codepage)+"\n")
+ if (self.film_analizer != None):
+ config_data.write("film_analizer:"+str(self.film_analizer)+"\n")
+ if (self.film_player != None):
+ config_data.write("film_player:"+str(self.film_player)+"\n")
+ if (self.film_converter != None):
+ config_data.write("film_converter:"+str(self.film_converter)+"\n")
+ if (self.menu_converter != None):
+ config_data.write("menu_converter:"+str(self.menu_converter)+"\n")
+ config_data.write("subtitle_font_size:"+str(self.subtitles_font_size)+"\n")
config_data.close()
except:
pass
+
+ def append_log(self,data,cr = True):
+
+ self.log+=data
+ if (cr):
+ self.log += "\n"
+
+ def clear_log(self):
+
+ self.log = ""
+
+ def get_log(self):
+
+ return self.log
\ No newline at end of file
diff --git a/src/devede/converter.py b/src/devede/converter.py
new file mode 100644
index 0000000..f71a6e3
--- /dev/null
+++ b/src/devede/converter.py
@@ -0,0 +1,115 @@
+# 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 devede.configuration_data
+import devede.mpv_converter
+
+class converter:
+
+ current_converter = None
+
+ @staticmethod
+ def get_converter():
+ if converter.current_converter == None:
+ converter.current_converter = converter.converter()
+ return converter.current_converter
+
+
+ def __init__(self):
+
+ self.config = devede.configuration_data.configuration.get_config()
+ self.c = [devede.mpv_converter.mpv_converter]
+
+ self.analizers = {}
+ self.default_analizer = None
+ self.players = {}
+ self.default_player = None
+ self.converters = {}
+ self.default_converter = None
+ self.menuers = {}
+ self.default_menuer = None
+
+ for element in self.c:
+ e = element()
+ if (e.check_is_installed() == False):
+ continue
+ name = e.display_name
+ if (e.supports_analize):
+ self.analizers[name] = element
+ if (self.default_analizer == None):
+ self.default_analizer = element
+ if (e.supports_play):
+ self.players[name] = element
+ if (self.default_player == None):
+ self.default_player = element
+ if (e.supports_convert):
+ self.converters[name] = element
+ if (self.default_converter == None):
+ self.default_converter = element
+ if (e.supports_menu):
+ self.menuers[name] = element
+ if (self.default_menuer == None):
+ self.default_menuer = element
+
+
+ def get_needed_programs(self):
+ """ returns a tupla with four lists. When a list is NONE, there are installed in the system
+ programs that covers the needs for that group; when not, it contains the programs valid
+ to cover the needs for that group.
+ The groups are, in this order: ANALIZERS, PLAYERS, CONVERTERS, MENUERS
+ (menuers are the programs that creates the mpeg files for menus)
+ """
+
+ if (self.default_analizer != None):
+ analizers = None
+ else:
+ analizers = []
+ if (self.default_player != None):
+ players = None
+ else:
+ players = []
+ if (self.default_converter != None):
+ converters = None
+ else:
+ converters = []
+ if (self.default_menuer != None):
+ menuers = None
+ else:
+ menuers = []
+
+ for element in self.c:
+ e = element()
+ name = e.display_name
+ if (e.supports_analize) and (analizers != None):
+ analizers.append(name)
+ if (e.supports_play) and (players != None):
+ players.append(name)
+ if (e.supports_convert) and (converters != None):
+ converters.append(name)
+ if (e.supports_menu) and (menuers != None):
+ menuers.append(name)
+
+ return ( analizers, players, converters, menuers )
+
+
+ def get_film_analizer(self):
+ """ returns a class for the desired film analizer, or the most priviledged if the desired is not installed """
+
+ if (self.config.film_analizer == None) or (self.analizers.has_key(self.config.film_analizer) == False):
+ return self.default_analizer
+ else:
+ return self.analizers[self.config.film_analizer]
diff --git a/src/devede/executor.py b/src/devede/executor.py
new file mode 100644
index 0000000..e388f58
--- /dev/null
+++ b/src/devede/executor.py
@@ -0,0 +1,32 @@
+#!/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 subprocess
+
+import devede.configuration_data
+
+class executor:
+ """ 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
diff --git a/src/devede/file_movie.py b/src/devede/file_movie.py
index 6b55ab4..54f95e0 100644
--- a/src/devede/file_movie.py
+++ b/src/devede/file_movie.py
@@ -17,72 +17,149 @@
from gi.repository import Gtk,GObject
import os
+
import devede.configuration_data
+import devede.interface_manager
+import devede.converter
-class file_movie(GObject.GObject):
+class file_movie(devede.interface_manager.interface_manager):
- counter2 = 0
+ __gsignals__ = {'title_changed': (GObject.SIGNAL_RUN_FIRST, None,(str,))}
def __init__(self,file_name):
GObject.GObject.__init__(self)
- self.config = devede.configuration_data.configuration.get_config()
- self.file_name = file_name
- self.title_name = os.path.splitext(os.path.basename(file_name))[0]
- self.wfile_properties = None
- self.model = None
- self.treeiter = None
- self.builder = None
-
- self.video_rate = 0
- self.audio_rate = 0
- self.final_size = None
- self.aspect_ratio = None
+ devede.interface_manager.interface_manager.__init__(self)
- def set_type(self,disc_type = None):
+ self.wfile_properties = None
+ self.builder = None
+
+ self.config = devede.configuration_data.configuration.get_config()
+ self.set_type(None, self.config.disc_type)
+ self.config.connect('disc_type',self.set_type)
+
+ self.add_text("file_name", file_name)
+ self.add_text("title_name", os.path.splitext(os.path.basename(file_name))[0])
+ self.add_label("original_size",None)
+ self.add_label("original_length",None)
+ self.add_label("original_videorate",None)
+ self.add_label("original_audiorate",None)
+ self.add_label("original_aspect_ratio",None)
+ self.add_label("original_fps",None)
+
+ self.add_toggle("show_in_menu", True)
+ self.add_toggle("format_pal",self.config.PAL)
+ self.add_toggle("video_rate_automatic", True)
+ self.add_toggle("audio_rate_automatic", True)
+ self.add_toggle("divide_in_chapters", True)
+ self.add_toggle("force_subtitles", False)
+ self.add_toggle("mirror_horizontal", False)
+ self.add_toggle("mirror_vertical", False)
+ self.add_toggle("two_pass_encoding", True)
+ self.add_toggle("sound5_1", False)
+ self.add_toggle("copy_sound", False)
+ self.add_toggle("is_mpeg_ps", False)
+ self.add_toggle("no_reencode_audio_video", False)
+ if (self.disc_type == "divx") or (self.disc_type == "mkv"):
+ self.add_toggle("gop12", False)
+ else:
+ self.add_toggle("gop12", True)
+
+ self.add_group("final_size_pal", ["size_auto", "size_1920x1080", "size_1280x720", "size_720x576", "size_704x576", "size_480x576","size_352x576", "size_352x288"], "size_auto")
+ self.add_group("final_size_ntsc", ["size_auto_ntsc", "size_1920x1080_ntsc", "size_1280x720_ntsc", "size_720x480", "size_704x480", "size_480x480","size_352x480", "size_352x240"], "size_auto_ntsc")
+ self.add_group("aspect_ratio", ["aspect_auto", "aspect_classic", "aspect_wide"], "aspect_auto")
+ self.add_group("scaling", ["add_black_bars", "scale_picture" ,"cut_picture"], "add_black_bars")
+ self.add_group("rotation",["rotation_0","rotation_90","rotation_180","rotation_270"], "rotation_0")
+ self.add_group("deinterlace", ["deinterlace_none", "deinterlace_ffmpeg", "deinterlace_yadif"], "deinterlace_none")
+ self.add_group("actions", ["action_stop","action_play_first","action__play_previous","action_play_again","action_play_next","action_play_last"], "action_stop")
+
+ self.add_integer_adjustment("volume", 100)
+ if (self.disc_type == "dvd"):
+ self.add_integer_adjustment("video_rate", 5000)
+ elif (self.disc_type == "vcd"):
+ self.add_integer_adjustment("video_rate", 1152)
+ else:
+ self.add_integer_adjustment("video_rate", 2000)
+ self.add_integer_adjustment("audio_rate", 224)
+ self.add_integer_adjustment("subt_font_size", 28)
+ self.add_float_adjustment("audio_delay", 0.0)
+
+ self.add_show_hide("format_pal", ["size_pal"], ["size_ntsc"])
+
+ self.add_enable_disable("divide_in_chapters", ["chapter_size_spinbutton"], [])
+ self.add_enable_disable("video_rate_automatic", [], ["video_spinbutton"])
+ self.add_enable_disable("audio_rate_automatic", [], ["audio_spinbutton"])
+ self.add_enable_disable("sound5_1", ["copy_sound"], [])
+
+ self.add_enable_disable("copy_sound", [], ["audio_delay_spinbutton","audio_rate_automatic","audio_spinbutton","spinbutton_volume","scale_volume","reset_volume"])
+
+ common_elements = ["gop12","video_rate_automatic","video_spinbutton","audio_rate_automatic","audio_spinbutton","format_pal","format_ntsc","spinbutton_volume","scale_volume","reset_volume",
+ "size_auto", "size_1920x1080", "size_1280x720", "size_720x576", "size_704x576", "size_480x576","size_352x576", "size_352x288",
+ "size_auto_ntsc", "size_1920x1080_ntsc", "size_1280x720_ntsc", "size_720x480", "size_704x480", "size_480x480","size_352x480", "size_352x240",
+ "aspect_auto","aspect_classic","aspect_wide","mirror_horizontal","mirror_vertical","add_black_bars","scale_picture","cut_picture",
+ "rotation_0","rotation_90","rotation_180","rotation_270","two_pass_encoding","deinterlace_none","deinterlace_ffmpeg","deinterlace_yadif",
+ "audio_delay_spinbutton","sound5_1","copy_sound"]
+
+ is_mpeg_ps_list = common_elements[:]
+ is_mpeg_ps_list.append("no_reencode_audio_video")
+ is_mpeg_ps_list.append("font_size_spinbutton")
+ is_mpeg_ps_list.append("force_subtitles")
+ is_mpeg_ps_list.append("button_add_subtitles")
+ is_mpeg_ps_list.append("button_del_subtitles")
+ no_reencode_audio_video_list = common_elements[:]
+ no_reencode_audio_video_list.append("is_mpeg_ps")
+
+ self.add_enable_disable("is_mpeg_ps", [], is_mpeg_ps_list)
+ self.add_enable_disable("no_reencode_audio_video", [], no_reencode_audio_video_list)
+ #self.add_enable_disable("", [], [])
+
+
+
+
+ #cv = devede.converter.converter()
+ #cv.get_film_data(self)
+
+ def set_type(self,obj = None,disc_type = None):
if (disc_type != None):
self.disc_type = disc_type
- if (disc_type == "dvd"):
- self.video_rate = 5000
- self.audio_rate = 224
- self.final_size = "size_auto"
- self.aspect_ratio = "aspect_auto"
- elif (disc_type == "vcd"):
- self.video_rate = 1152
- self.audio_rate = 224
- self.final_size = "size_352x288"
- self.aspect_ratio = "aspect_classic"
- elif (disc_type == "svcd"):
- self.video_rate = 2000
- self.audio_rate = 224
- self.final_size = "size_480x576"
- self.aspect_ratio = "aspect_classic"
- elif (disc_type == "cvd"):
- self.video_rate = 2000
- self.audio_rate = 224
- self.final_size = "size_352x576"
- self.aspect_ratio = "aspect_classic"
- elif (disc_type == "divx"):
- self.video_rate = 5000
- self.audio_rate = 224
- self.final_size = "size_auto"
- self.aspect_ratio = "aspect_auto"
+
+ if (disc_type == "vcd"):
+ self.final_size_auto_width = 352
+ self.final_size_auto_height_pal = 288
+ self.final_size_auto_height_ntsc = 240
+ self.video_rate_auto_value = 1152
+ self.audio_rate_auto_value = 224
+ elif (disc_type == "svcd"):
+ self.final_size_auto_width = 480
+ self.final_size_auto_height_pal = 576
+ self.final_size_auto_height_ntsc = 480
+ self.video_rate_auto_value = -1
+ self.audio_rate_auto_value = -1
+ elif (disc_type == "cvd"):
+ self.final_size_auto_width = 352
+ self.final_size_auto_height_pal = 576
+ self.final_size_auto_height_ntsc = 480
+ self.video_rate_auto_value = -1
+ self.audio_rate_auto_value = -1
+ else: # dvd, divx and mkv
+ self.final_size_auto_width = -1
+ self.final_size_auto_height_pal = -1
+ self.final_size_auto_height_ntsc = -1
+ self.video_rate_auto_value = -1
+ self.audio_rate_auto_value = -1
def delete_file(self):
print("Deleted file "+self.file_name)
- def properties(self,model,treeiter):
-
+ def properties(self):
+
if (self.wfile_properties != None):
self.wfile_properties.present()
return
-
- self.model = model
- self.treeiter = treeiter
-
+
self.builder = Gtk.Builder()
self.builder.set_translation_domain(self.config.gettext_domain)
@@ -90,25 +167,89 @@ class file_movie(GObject.GObject):
self.builder.connect_signals(self)
self.wfile_properties = self.builder.get_object("file_properties")
self.wfile_properties.show_all()
-
- self.wfile = self.builder.get_object("label_filename")
- self.wtitle = self.builder.get_object("entry_title")
-
- self.wfile.set_text(self.file_name)
- self.wtitle.set_text(self.title_name)
-
+
+ self.wshow_in_menu = self.builder.get_object("show_in_menu")
+
+ self.wnotebook = self.builder.get_object("notebook")
+
+ # elements in page GENERAL
+ self.wframe_video_rate = self.builder.get_object("frame_video_rate")
+ self.wframe_audio_rate = self.builder.get_object("frame_audio_rate")
+ self.wframe_division_chapters = self.builder.get_object("frame_division_chapters")
+
+ # elements in page VIDEO OPTIONS
+ self.wsize_1920x1080 = self.builder.get_object("size_1920x1080")
+ self.wsize_1280x720 = self.builder.get_object("size_1280x720")
+ self.wsize_1920x1080_ntsc = self.builder.get_object("size_1920x1080_ntsc")
+ self.wsize_1280x720_ntsc = self.builder.get_object("size_1280x720_ntsc")
+ self.wframe_final_size = self.builder.get_object("frame_final_size")
+ self.wframe_aspect_ratio = self.builder.get_object("frame_aspect_ratio")
+
+ # elements in page AUDIO
+ self.wsound5_1 = self.builder.get_object("sound5_1")
+ self.wcopy_sound = self.builder.get_object("copy_sound")
+
+ # Adjust the interface UI to the kind of disc
+
+ if (self.disc_type == 'dvd'):
+ self.wsize_1920x1080.hide()
+ self.wsize_1280x720.hide()
+ self.wsize_1920x1080_ntsc.hide()
+ self.wsize_1280x720_ntsc.hide()
+ elif (self.disc_type == 'vcd'):
+ self.wshow_in_menu.hide()
+ self.wframe_video_rate.hide()
+ self.wframe_audio_rate.hide()
+ self.wframe_division_chapters.hide()
+ self.wframe_final_size.hide()
+ self.wframe_aspect_ratio.hide()
+ self.wsound5_1.hide()
+ self.wcopy_sound.hide()
+ self.wnotebook.remove_page(5)
+ elif (self.disc_type == 'svcd'):
+ self.wsize_1920x1080.hide()
+ self.wsize_1280x720.hide()
+ self.wsize_1920x1080_ntsc.hide()
+ self.wsize_1280x720_ntsc.hide()
+ self.wshow_in_menu.hide()
+ self.wframe_division_chapters.hide()
+ self.wframe_aspect_ratio.hide()
+ self.wsound5_1.hide()
+ self.wcopy_sound.hide()
+ self.wnotebook.remove_page(5)
+ elif (self.disc_type == 'cvd'):
+ self.wsize_1920x1080.hide()
+ self.wsize_1280x720.hide()
+ self.wsize_1920x1080_ntsc.hide()
+ self.wsize_1280x720_ntsc.hide()
+ self.wshow_in_menu.hide()
+ self.wframe_division_chapters.hide()
+ self.wframe_aspect_ratio.hide()
+ self.wsound5_1.hide()
+ self.wcopy_sound.hide()
+ self.wnotebook.remove_page(5)
+ elif (self.disc_type == 'divx'):
+ self.wshow_in_menu.hide()
+ self.wframe_division_chapters.hide()
+ self.wsound5_1.hide()
+ self.wcopy_sound.hide()
+ self.wnotebook.remove_page(5)
+ self.wnotebook.remove_page(1)
+ elif (self.disc_type == 'mkv'):
+ self.wshow_in_menu.hide()
+ self.wframe_division_chapters.hide()
+ self.wnotebook.remove_page(5)
+
+ self.update_ui(self.builder)
+
def on_button_accept_clicked(self,b):
- self.title_name = self.wtitle.get_text()
- self.model.set_value(self.treeiter,1,self.title_name)
+ self.store_ui(self.builder)
+ self.emit('title_changed',self.title_name)
self.on_button_cancel_clicked(None)
-
+
def on_button_cancel_clicked(self,b):
-
+
self.wfile_properties.destroy()
self.wfile_properties = None
self.builder = None
- self.model = None
- self.treeiter = None
-
-
\ No newline at end of file
diff --git a/src/devede/interface_manager.py b/src/devede/interface_manager.py
new file mode 100644
index 0000000..986ecd7
--- /dev/null
+++ b/src/devede/interface_manager.py
@@ -0,0 +1,266 @@
+# 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 GObject
+
+class interface_manager(GObject.GObject):
+ """ This class allows to automatically generate variables for a GLADE interface,
+ set the widgets in the interface to their values, and copy the current values
+ in the widgets to the variables """
+
+ def __init__(self):
+
+ self.groups = {}
+ self.toggles = []
+ self.labels = []
+ self.text = []
+ self.show_hide = []
+ self.enable_disable = []
+ self.float_adjustments = []
+ self.integer_adjustments = []
+
+ def add_group(self,group_name,radiobutton_list,default_value):
+ """ Adds a group of radiobuttons and creates an internal variable with
+ the name group_name, setting it to default_value. The
+ value for the variable will be the name of the active
+ radiobutton """
+
+ if (default_value != None):
+ exec('self.'+group_name+' = "'+str(default_value)+'"')
+ else:
+ exec('self.'+group_name+' = None')
+ self.groups[group_name] = radiobutton_list
+
+ def add_toggle(self,toggle_name,default_value):
+ """ Adds an internal variable with the name toggle_name, linked to a widget
+ element with the same name (must be or inherint from Gtk.ToogleButton).
+ The default value can be True of False """
+
+ exec('self.'+toggle_name+' = '+str(default_value))
+ self.toggles.append(toggle_name)
+
+ def add_text(self,text_name,default_value):
+ """ Adds an internal variable with the name text_name, linked to an
+ element with the same name (must be a Gtk.TextEntry or a Gtk.Label).
+ The default value can be a text or None """
+
+ if (default_value != None):
+ exec('self.'+text_name+' = "'+str(default_value)+'"')
+ else:
+ exec('self.'+text_name+' = None')
+ self.text.append(text_name)
+
+ def add_label(self,text_name,default_value):
+ """ Adds an internal variable with the name text_name, linked to an
+ element with the same name (must be a Gtk.TextEntry or a Gtk.Label).
+ The default value can be a text or None. This element is copied to the UI,
+ but is never updated from the UI if the user changes it """
+
+ exec('self.'+text_name+' = default_value')
+ self.labels.append(text_name)
+
+ def add_integer_adjustment(self,adjustment_name,default_value):
+ """ Adds an internal variable with the name text_name, linked to an
+ element with the same name (must be a Gtk.Adjustment).
+ The default value must be an integer """
+
+ exec('self.'+adjustment_name+' = '+str(default_value))
+ self.integer_adjustments.append(adjustment_name)
+
+ def add_float_adjustment(self,adjustment_name,default_value):
+ """ Adds an internal variable with the name text_name, linked to an
+ element with the same name (must be a Gtk.Adjustment).
+ The default value must be an float """
+
+ exec('self.'+adjustment_name+' = '+str(default_value))
+ self.float_adjustments.append(adjustment_name)
+
+
+ def add_show_hide(self,element_name,to_show,to_hide):
+ """ Adds an element that can be active or inactive, and two lists of elements.
+ The first one contains elements that will be visible when the element is
+ active, and invisible when it is inactive, and the second one contains
+ elements that will be visible when the element is inactive, and
+ invisible when the element is active """
+
+ self.show_hide.append([element_name, to_show, to_hide])
+
+ def add_enable_disable(self,element_name,to_enable,to_disable):
+ """ Adds an element that can be active or inactive, and two lists of elements.
+ The first one contains elements that will be enabled when the element is
+ active, and disabled when it is inactive, and the second one contains
+ elements that will be enabled when the element is inactive, and
+ disabled when the element is active """
+
+ self.enable_disable.append([element_name, to_enable, to_disable])
+
+ def update_ui(self,builder):
+ """ Sets the value of the widgets in base of the internal variables """
+
+ for key in self.groups:
+ obj = eval('self.'+key)
+ builder.get_object(obj).set_active(True)
+
+ for element in self.toggles:
+ value = eval('self.'+element)
+ builder.get_object(element).set_active(value)
+
+ for element in self.text:
+ value = eval('self.'+element)
+ if (value != None):
+ builder.get_object(element).set_text(value)
+ else:
+ builder.get_object(element).set_text("")
+
+ for element in self.labels:
+ value = eval('self.'+element)
+ if (value != None):
+ builder.get_object(element).set_text(str(value))
+ else:
+ builder.get_object(element).set_text("")
+
+ for element in self.integer_adjustments:
+ value = eval('self.'+element)
+ builder.get_object(element).set_value(float(value))
+
+ for element in self.float_adjustments:
+ value = eval('self.'+element)
+ builder.get_object(element).set_value(value)
+
+ self.show_hide_obj = {}
+ for element in self.show_hide:
+ obj = builder.get_object(element[0])
+ to_show = []
+ for e2 in element[1]:
+ to_show.append(builder.get_object(e2))
+ to_hide = []
+ for e3 in element[2]:
+ to_hide.append(builder.get_object(e3))
+ self.show_hide_obj[obj] = [to_show, to_hide]
+ obj.connect('toggled',self.toggled_element)
+ self.toggled_element(obj)
+
+ self.enable_disable_obj = {}
+ for element in self.enable_disable:
+ obj = builder.get_object(element[0])
+ to_enable = []
+ for e2 in element[1]:
+ to_enable.append(builder.get_object(e2))
+ to_disable = []
+ for e3 in element[2]:
+ to_disable.append(builder.get_object(e3))
+ self.enable_disable_obj[obj] = [to_enable, to_disable]
+ obj.connect('toggled',self.toggled_element2)
+ self.toggled_element2(obj)
+
+ def toggled_element(self,element):
+ """ Wenever an element with 'hide' or 'show' needs is toggled, this callback is called """
+
+ # First, show all items for each possible element
+ for key in self.show_hide_obj:
+ to_show = self.show_hide_obj[key][0]
+ to_hide = self.show_hide_obj[key][1]
+
+ active = key.get_active()
+
+ for item in to_show:
+ if active:
+ item.show()
+
+ for item in to_hide:
+ if not active:
+ item.show()
+
+ # And now, hide all items that must be hiden
+ # This is done this way because this allows to have an item being hiden by
+ # one widget, and being shown by another: in that case, it will be hiden always
+ for key in self.show_hide_obj:
+ to_show = self.show_hide_obj[key][0]
+ to_hide = self.show_hide_obj[key][1]
+
+ active = key.get_active()
+
+ for item in to_show:
+ if not active:
+ item.hide()
+
+ for item in to_hide:
+ if active:
+ item.hide()
+
+
+ def toggled_element2(self,element):
+ """ Wenever an element with 'enable' or 'disable' needs is toggled, this callback is called """
+
+ # First enable all items that must be enabled
+ for key in self.enable_disable_obj:
+ to_enable = self.enable_disable_obj[key][0]
+ to_disable = self.enable_disable_obj[key][1]
+
+ active = key.get_active()
+ if (active):
+ for item in to_enable:
+ item.set_sensitive(True)
+ else:
+ for item in to_disable:
+ item.set_sensitive(True)
+
+ # And now, disable all items that must be disabled
+ # This is done this way because this allows to have an item being disabled by
+ # one widget, and being enabled by another: in that case, it will be disabled always
+ for key in self.enable_disable_obj:
+ to_enable = self.enable_disable_obj[key][0]
+ to_disable = self.enable_disable_obj[key][1]
+
+ active = key.get_active()
+ if (not active):
+ for item in to_enable:
+ item.set_sensitive(False)
+ else:
+ for item in to_disable:
+ item.set_sensitive(False)
+
+ def store_ui(self,builder):
+ """ Takes the values of the widgets and stores them in the internal variables """
+
+ for key in self.groups:
+ for element in self.groups[key]:
+ obj = builder.get_object(element)
+ if obj.get_active():
+ exec('self.'+key+' = "'+element+'"')
+ break
+
+ for element in self.toggles:
+ obj = builder.get_object(element)
+ if obj.get_active():
+ exec('self.'+element+' = True')
+ else:
+ exec('self.'+element+' = False')
+
+ for element in self.text:
+ obj = builder.get_object(element)
+ exec('self.'+element+' = obj.get_text()')
+
+ for element in self.integer_adjustments:
+ obj = builder.get_object(element)
+ exec('self.'+element+' = int(obj.get_value())')
+
+ for element in self.float_adjustments:
+ obj = builder.get_object(element)
+ exec('self.'+element+' = obj.get_value()')
+
+
\ No newline at end of file
diff --git a/src/devede/mpv_converter.py b/src/devede/mpv_converter.py
new file mode 100644
index 0000000..f132104
--- /dev/null
+++ b/src/devede/mpv_converter.py
@@ -0,0 +1,105 @@
+# 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 subprocess
+import devede.configuration_data
+
+class mpv_converter:
+
+ def __init__(self):
+
+ self.config = devede.configuration_data.configuration.get_config()
+ self.supports_analize = True
+ self.supports_play = True
+ self.supports_convert = False
+ self.supports_menu = False
+ self.display_name = "MPV"
+
+ def check_is_installed(self):
+ handle = subprocess.Popen(["mpv","-v"])
+ if 0==handle.wait():
+ return True
+ else:
+ return False
+
+ def get_film_data(self,movie):
+ """ processes a file, refered by the FILE_MOVIE movie object, and fills its
+ main data (resolution, FPS, length...) """
+
+ def get_film_data2(self,movie,check_audio):
+
+ if (check_audio):
+ frames = "0"
+ else:
+ frames = "1"
+
+ if self.config.mpv_available:
+ command_line = ["mpv","identify","-loop","1","-identify", "-ao", "null", "-vo", "null", "-frames", "1"]
+ else:
+ command_line = ["mplayer","identify","-loop","1","-identify", "-ao", "null", "-vo", "null", "-frames", "1"]
+
+ command_line.append(movie.file_name)
+
+ handle = subprocess.Popen(command_line)
+ (stdout, stderr) = handle.communicate()
+
+ minimum_audio=-1
+ audio_list=[]
+ audio = 0
+ video = 0
+
+ for line in stdout:
+ line=self.remove_ansi(line)
+ if line == "":
+ continue
+ position=line.find("ID_")
+ if position==-1:
+ continue
+ line=line[position:]
+ if line[:16]=="ID_VIDEO_BITRATE":
+ vrate=int(line[17:])
+ if line[:14]=="ID_VIDEO_WIDTH":
+ width=int(line[15:])
+ if line[:15]=="ID_VIDEO_HEIGHT":
+ height=int(line[16:])
+ if line[:15]=="ID_VIDEO_ASPECT":
+ aspect_ratio=float(line[16:])
+ if line[:12]=="ID_VIDEO_FPS":
+ fps2=line[13:]
+ while ord(fps2[-1])<32:
+ fps2=fps2[:-1]
+ posic=line.find(".")
+ if posic==-1:
+ fps=int(line[13:])
+ else:
+ fps=int(line[13:posic])
+ if line[posic+1]=="9":
+ fps+=1
+ if line[:16]=="ID_AUDIO_BITRATE":
+ arate=int(line[17:])
+ if line[:13]=="ID_AUDIO_RATE":
+ audiorate=int(line[14:])
+ if line[:9]=="ID_LENGTH":
+ length=int(float(line[10:]))
+ if line[:11]=="ID_VIDEO_ID":
+ video+=1
+ if line[:11]=="ID_AUDIO_ID":
+ audio+=1
+ audio_track=int(line[12:])
+ if (minimum_audio == -1) or (minimum_audio>audio_track):
+ minimum_audio=audio_track
+ audio_list.append(audio_track)
\ No newline at end of file
diff --git a/src/devede/project.py b/src/devede/project.py
index 1634c44..ce8ce33 100644
--- a/src/devede/project.py
+++ b/src/devede/project.py
@@ -27,83 +27,62 @@ class devede_project:
def __init__(self):
self.config = devede.configuration_data.configuration.get_config()
- self.destroy_all()
+ self.disc_type = self.config.disc_type
- def destroy_all(self):
-
- self.wask_window = None
- self.wmain_window = None
- self.wdisc_size = None
- self.wliststore_files = None
- self.wfiles = None
- self.wdisc_fill_level = None
- self.wuse_pal = None
- self.wuse_ntsc = None
- self.wcreate_menu = None
- self.disc_type = None
- self.wadd_file = None
- self.wdelete_file = None
- self.wup_file = None
- self.wdown_file = None
- self.wproperties_file = None
- self.wcreate_disc = None
-
-
- def ask_type(self):
- """ This method resets the project and asks the user what kind of project want to do """
-
- if (self.wask_window != None):
- self.wask_window.present()
- return
+ self.current_title = None
builder = Gtk.Builder()
builder.set_translation_domain(self.config.gettext_domain)
- builder.add_from_file(os.path.join(self.config.glade,"wselect_disk.ui"))
+ builder.add_from_file(os.path.join(self.config.glade,"wmain.ui"))
builder.connect_signals(self)
- self.wask_window = builder.get_object("wselect_disk")
- self.wask_window.show_all()
- def on_wselect_disk_delete_event(self,w,e):
- Gtk.main_quit()
- return False
+ # Interface widgets
+ self.wmain_window = builder.get_object("wmain_window")
+ self.wdisc_size = builder.get_object("disc_size")
+ self.wliststore_files = builder.get_object("liststore_files")
+ self.wfiles = builder.get_object("files")
+ self.wdisc_fill_level = builder.get_object("disc_fill_level")
+ self.wuse_pal = builder.get_object("use_pal")
+ self.wuse_ntsc = builder.get_object("use_ntsc")
+ self.wcreate_menu = builder.get_object("create_menu")
+ self.wframe_titles = builder.get_object("frame_titles")
- def on_button_dvd_clicked(self,b):
+ self.wadd_file = builder.get_object("add_file")
+ self.wdelete_file = builder.get_object("delete_file")
+ self.wup_file = builder.get_object("up_file")
+ self.wdown_file = builder.get_object("down_file")
+ self.wproperties_file = builder.get_object("properties_file")
+ self.wpreview_file = builder.get_object("preview_file")
- self.set_type("dvd")
+ self.wcreate_disc = builder.get_object("create_disc")
- def on_button_vcd_clicked(self,b):
+ selection = self.wfiles.get_selection()
+ selection.mode = Gtk.SelectionMode.SINGLE
- self.set_type("vcd")
+ if (self.config.PAL):
+ self.wuse_pal.set_active(True)
+ else:
+ self.wuse_ntsc.set_active(True)
- def on_button_svcd_clicked(self,b):
-
- self.set_type("svcd")
-
- def on_button_cvd_clicked(self,b):
-
- self.set_type("cvd")
-
- def on_button_divx_clicked(self,b):
-
- self.set_type("divx")
+ self.config.connect('disc_type',self.set_type)
+ if (self.disc_type != None):
+ self.set_type(None, self.disc_type)
- def set_type(self,disc_type):
+ def set_type(self,obj=None,disc_type=None):
""" this method sets the disk type to the specified one and adapts the interface
in the main window to it. Also leaves everything ready to start creating a
new disc """
- if (self.wask_window != None):
- self.wask_window.destroy()
- self.destroy_all()
-
- self.disc_type = disc_type
- self.show_main_window()
+ if (disc_type != None):
+ self.disc_type = disc_type
+ self.wmain_window.show_all()
+ self.set_interface_status(None)
# Set the default disc size
- if (self.disc_type == "dvd"):
+ if (self.disc_type == "dvd") or (self.disc_type == "mkv"):
self.wdisc_size.set_active(1) # 4.7 GB DVD
else:
self.wdisc_size.set_active(3) # 700 MB CD
@@ -156,52 +135,8 @@ class devede_project:
self.wdown_file.set_sensitive(False)
- def show_main_window(self):
-
- if (self.wmain_window != None):
- self.wmain_window.present()
- return
-
- self.current_title = None
-
- builder = Gtk.Builder()
- builder.set_translation_domain(self.config.gettext_domain)
-
- builder.add_from_file(os.path.join(self.config.glade,"wmain.ui"))
- builder.connect_signals(self)
-
- # Interface widgets
- self.wmain_window = builder.get_object("wmain_window")
- self.wdisc_size = builder.get_object("disc_size")
- self.wliststore_files = builder.get_object("liststore_files")
- self.wfiles = builder.get_object("files")
- self.wdisc_fill_level = builder.get_object("disc_fill_level")
- self.wuse_pal = builder.get_object("use_pal")
- self.wuse_ntsc = builder.get_object("use_ntsc")
- self.wcreate_menu = builder.get_object("create_menu")
- self.wframe_titles = builder.get_object("frame_titles")
-
- self.wadd_file = builder.get_object("add_file")
- self.wdelete_file = builder.get_object("delete_file")
- self.wup_file = builder.get_object("up_file")
- self.wdown_file = builder.get_object("down_file")
- self.wproperties_file = builder.get_object("properties_file")
- self.wpreview_file = builder.get_object("preview_file")
-
- self.wcreate_disc = builder.get_object("create_disc")
-
- selection = self.wfiles.get_selection()
- selection.mode = Gtk.SelectionMode.SINGLE
-
- if (self.config.PAL):
- self.wuse_pal.set_active(True)
- else:
- self.wuse_ntsc.set_active(True)
- self.wmain_window.show_all()
- self.set_interface_status(None)
-
def on_use_pal_toggled(self,b):
-
+
self.config.PAL = self.wuse_pal.get_active()
def on_wmain_window_delete_event(self,b,e=None):
@@ -211,14 +146,21 @@ class devede_project:
Gtk.main_quit()
return True
+ def title_changed(self,obj,new_title):
+
+ for item in self.wliststore_files:
+ element = item.model[item.iter][0]
+ if element == obj:
+ item.model.set_value(item.iter,1,new_title)
+
+
def on_add_file_clicked(self,b):
ask_files = devede.add_files.add_files()
- ask_files.set_type(self.disc_type)
if (ask_files.run()):
for efile in ask_files.files:
new_file = devede.file_movie.file_movie(efile)
- new_file.set_type(self.disc_type)
+ new_file.connect('title_changed',self.title_changed)
self.wliststore_files.append([new_file, new_file.title_name])
self.set_interface_status(None)
@@ -259,8 +201,7 @@ class devede_project:
(element, position, model, treeiter) = self.get_current_file()
if (element == None):
return
-
- element.properties(model,treeiter)
+ element.properties()
def on_adjust_disc_usage_clicked(self,b):
diff --git a/src/devede_ng.py b/src/devede_ng.py
index 9af26e1..bbd0309 100755
--- a/src/devede_ng.py
+++ b/src/devede_ng.py
@@ -24,10 +24,11 @@ from gi.repository import Gtk
import devede.project
import devede.configuration_data
+import devede.choose_disc_type
config_data = devede.configuration_data.configuration.get_config()
-if config_data.error:
+if config_data == None:
print ("Can't locate extra files. Aborting.")
sys.exit(1)
@@ -44,6 +45,6 @@ _ = gettext.gettext
Gtk.init(sys.argv)
mwindow = devede.project.devede_project()
-mwindow.ask_type()
+ask_type = devede.choose_disc_type.choose_disc_type()
Gtk.main()
config_data.save_config()