diff --git a/opendvdproducer.py b/opendvdproducer.py new file mode 100644 index 0000000..b0630e4 --- /dev/null +++ b/opendvdproducer.py @@ -0,0 +1,3684 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import os, sys, subprocess, time, random, codecs, tempfile, shutil, shutil + +from PySide import QtGui, QtCore +from PySide.phonon import Phonon + +reload(sys) +sys.setdefaultencoding("utf-8") + +if sys.platform == 'win32': + path_opendvdproducer = getattr(sys, '_MEIPASS', os.getcwd()) + +else: + path_opendvdproducer = os.path.dirname(sys.argv[0]) + +#os.path.realpath(__file__)#os.path.abspath(os.path.dirname(sys.argv[0])) + +path_graphics = os.path.join(path_opendvdproducer, 'graphics') +path_home = os.environ.get('HOME', None) + +path_tmp = os.path.join(tempfile.gettempdir(), 'opendvdproducer-' + str(random.randint(1000,9999))) + +if sys.platform == 'darwin': + iso2ddp_bin = os.path.join(path_opendvdproducer, 'iso2ddp_mac') + imagemagick_convert_bin = os.path.join(path_opendvdproducer, 'convert') + interface_font_size = 12 + ffprobe_bin = os.path.join(path_opendvdproducer, 'ffprobe') + ffmpeg_bin = os.path.join(path_opendvdproducer, 'ffmpeg') + spumux_bin = os.path.join(path_opendvdproducer, 'spumux') + dvdauthor_bin = os.path.join(path_opendvdproducer, 'dvdauthor') + mkisofs_bin = os.path.join(path_opendvdproducer, 'mkisofs') + md5_bin = '/sbin/md5' + split_bin = '/usr/bin/split' + +elif sys.platform == 'win32': + iso2ddp_bin = os.path.join(path_opendvdproducer, 'iso2ddp.exe') + imagemagick_convert_bin = os.path.join(path_opendvdproducer, 'convert.exe') + ffprobe_bin = os.path.join(path_opendvdproducer, 'ffprobe.exe') + ffmpeg_bin = os.path.join(path_opendvdproducer, 'ffmpeg.exe') + spumux_bin = os.path.join(path_opendvdproducer, 'spumux.exe') + dvdauthor_bin = os.path.join(path_opendvdproducer, 'dvdauthor.exe') + mkisofs_bin = os.path.join(path_opendvdproducer, 'mkisofs.exe') + md5_bin = os.path.join(path_opendvdproducer, 'md5.exe') + split_bin = os.path.join(path_opendvdproducer, 'split.exe') + interface_font_size = 9 +else: + if subprocess.call("type ffprobe", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0: + ffprobe_bin = 'ffprobe' + else: + ffprobe_bin = 'avprobe' + if subprocess.call("type ffmpeg", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0: + ffmpeg_bin = 'ffmpeg' + else: + ffmpeg_bin = 'avconv' + spumux_bin = 'spumux' + dvdauthor_bin = 'dvdauthor' + mkisofs_bin = 'mkisofs' + md5_bin = 'md5sum' + split_bin = 'split' + iso2ddp_bin = os.path.join(path_opendvdproducer, 'resources', 'iso2ddp') + imagemagick_convert_bin = 'convert' + interface_font_size = 10 + +os.mkdir(path_tmp) + +class generate_dvd_thread_signal(QtCore.QObject): + sig = QtCore.Signal(str) + +class generate_dvd_thread(QtCore.QThread): + def __init__(self, parent = None): + QtCore.QThread.__init__(self, parent) + self.actual_project_file = '' + self.project_name = 'Untitled' + self.audio_codec = 'ac3' + self.framerate = '25' + self.height = 480 + self.video_format = 'pal' + self.video_resolutions = ['720x480'] + self.aspect_ratio = '16:9' + self.list_of_menus = [] + self.list_of_videos = [] + self.dict_of_menus = [] + self.dict_of_videos = [] + self.selected_gop_size = 12 + self.selected_menu_bitrate = 7500 + self.selected_menu_max_bitrate = 9000 + self.selected_video_bitrate = 7500 + self.selected_video_max_bitrate = 9000 + self.selected_menu_encoding = 'CBR' + self.selected_video_encoding = 'CBR' + self.selected_menu_twopass = True + self.selected_video_twopass = True + self.audio_datarate = 384 + self.generate_ddp = False + self.generate_iso = True + self.has_menus = True + + self.signal = generate_dvd_thread_signal() + + def run(self): + def generate_ddp(original_file, output_path): + split_area = 4699979776 + if os.path.getsize(original_file) < split_area: + subprocess.call([iso2ddp_bin, '--inputfile=' + original_file, '--outputpath=' + output_path]) + else: + subprocess.call([iso2ddp_bin, '--inputfile=' + original_file, '--layers=2', '--layer=1' '--outputpath=' + output_path]) + subprocess.call([iso2ddp_bin, '--inputfile=' + original_file, '--layers=2', '--layer=2' '--outputpath=' + output_path]) + + output_path = output_path + '_TEST' + + sides = 1 + actual_side = 0 + disc_size = 'B' #Disc size "B" = 12cm, "A" = 8cm * + tp_mode = "PTP" + + if os.path.getsize(original_file) < split_area: + layers = ['Layer0'] + else: + layers = ['Layer0', 'Layer1'] + + if not os.path.isdir(output_path): + subprocess.call(['mkdir', output_path]) + + actual_layer = 0 + main_size = os.path.getsize(original_file)/2048 + for layer in layers: + subprocess.call(['mkdir', os.path.join(output_path, layer)]) + + if len(layers) == 1: + layer_size = main_size + layer0_size = main_size + else: + layer0_size = split_area/2048 + if actual_layer == 0: + layer_size = split_area/2048 + else: + layer_size = main_size - (split_area/2048) + + ddpid = str( + "DDP 2.00" + + " " + + " " + + " " + + " " + + " " + + " " + + "DV" + + str(sides) + + str(actual_side) + + str(len(layers)) + + str(actual_layer) + + "I" + + disc_size + + "0" + + "0" + + " " + + " " + + + "VVVM" + + "D2" + + " " + + "00000016" + + "00193024" + + " " + + "DV" + + "1" + + "0" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + "017" + "CONTROL.DAT " + + " " + + " " + + " " + + " " + + " " + + + "VVVM" + + "D0" + + " " + + str("%08d" % int(layer_size)) + + "00196608" + + " " + + "DV" + + "0" + + "0" + + " " + + " " + + " " + + " " + + " " + + " " + + " " + + "017" + "MAIN.DAT " + + " " + + " " + + " " + + " " + + " " + ) + + open(os.path.join(output_path, layer, 'DDPID'), 'w').write(ddpid) + + control_dat = '' + control_dat += str(bytearray([int('00000000', 2)])) + control_dat += str(bytearray([int('00000000', 2)])) + control_dat += str(bytearray([int('00000000', 2)])) + control_dat += str(bytearray([int('00000000', 2)])) + control_dat += str(bytearray([int('00000000', 2)])) + control_dat += str(bytearray([int('00000000', 2)])) + control_dat += str(bytearray([int('00000001', 2)])) + + + control_dat += str(bytearray([int('00000010', 2)])) + + + + + + + if len(layers) == 2: + if tp_mode == "OTP": + control_dat += str(bytearray([int('00110001', 2)])) + else: + control_dat += str(bytearray([int('00100001', 2)])) + else: + if tp_mode == "OTP": + control_dat += str(bytearray([int('00010001', 2)])) + else: + control_dat += str(bytearray([int('00000001', 2)])) + + control_dat += str(bytearray([int('00010000', 2)])) + + + + + + control_dat += str(bytearray([int('00000000', 2)])) + control_dat += str(bytearray([int('00000011', 2)])) + control_dat += str(bytearray([int('00000000', 2)])) + control_dat += str(bytearray([int('00000000', 2)])) + control_dat += str(bytearray([int('00000000', 2)])) + control_dat += str(('%%0%dx' % (3 << 1) % int(196608 + main_size - 1)).decode('hex')[-3:]) + control_dat += str(bytearray([int('00000000', 2)])) + + if tp_mode == "OTP" and len(layers) == 2: + control_dat += str(('%%0%dx' % (3 << 1) % int(196608 + layer0_size - 1)).decode('hex')[-3:]) + else: + control_dat += str(bytearray([int('00000000', 2)])) + control_dat += str(bytearray([int('00000000', 2)])) + control_dat += str(bytearray([int('00000000', 2)])) + + control_dat += str(bytearray([int('00000000', 2)])) + + + + + + for i in range(16): + control_dat += str(bytearray([int('00000000', 2)])) + + for i in range(2015): + control_dat += str(bytearray([int('00000000', 2)])) + + for i in range(6): + control_dat += str(bytearray([int('00000000', 2)])) + for i in range(2048): + control_dat += str(bytearray([int('00000000', 2)])) + + for i in range(14): + for j in range(6): + control_dat += str(bytearray([int('00000000', 2)])) + for j in range(2048): + control_dat += str(bytearray([int('00000000', 2)])) + + open(os.path.join(output_path, layer, 'CONTROL.DAT'), 'w').write(control_dat) + + actual_layer += 1 + + if len(layers) == 2: + subprocess.call([split_bin, '-b=' + str(split_area), os.path.join(path_tmp, 'movie.iso'), os.path.join(path_tmp, 'movie.iso_part')]) + shutil.move(os.path.join(path_tmp, 'movie.iso_part.aa'), os.path.join(output_path, 'Layer0', 'MAIN.DAT')) + shutil.move(os.path.join(path_tmp, 'movie.iso_part.ab'), os.path.join(output_path, 'Layer1', 'MAIN.DAT')) + else: + shutil.copy(os.path.join(path_tmp, 'movie.iso'), os.path.join(output_path, 'Layer0', 'MAIN.DAT')) + + total_progress = str(len(self.list_of_videos) + len(self.list_of_menus) + 8) + + self.signal.sig.emit('START,0,' + total_progress) + + if not os.path.isdir(os.path.join(path_tmp, 'dvd')): + os.mkdir(os.path.join(path_tmp, 'dvd')) + + final_dvd_author_xml = '' + + list_of_used_videos = [] + for video in self.list_of_videos: + list_of_used_videos.append(video) + + intro_video = False + for video in self.list_of_videos: + if self.dict_of_videos[video][3]: + intro_video = video + break + + final_dvd_author_xml += '' + final_dvd_author_xml += '' + + menu_count = 1 + if self.has_menus: + final_dvd_author_xml += '' + + final_dvd_author_xml += '' + final_project_file += '' + for video in self.list_of_videos: + final_project_file += '' + final_project_file += '' + final_project_file += '' + + return final_project_file + +def options_panel_dvd_panel_bitrates_changed(self): + self.selected_menu_bitrate = self.options_panel_dvd_panel_menu_bitrate_field.value() + self.selected_menu_max_bitrate = self.options_panel_dvd_panel_menu_max_bitrate_field.value() + self.selected_video_bitrate = self.options_panel_dvd_panel_video_bitrate_field.value() + self.selected_video_max_bitrate = self.options_panel_dvd_panel_video_max_bitrate_field.value() + update_changes(self) + +def options_panel_dvd_panel_gop_changed(self): + self.really_clean_project = False + self.selected_gop_size = int(self.options_panel_dvd_panel_gop.currentText()) + update_changes(self) + +def options_panel_dvd_panel_audio_datarate_changed(self): + self.really_clean_project = False + self.selected_audio_datarate = self.options_panel_dvd_panel_audio_datarate.currentText() + update_changes(self) + +def options_panel_dvd_panel_menu_encoding_changed(self): + if self.selected_menu_encoding == 'CBR': + self.selected_menu_encoding = 'VBR' + else: + self.selected_menu_encoding = 'CBR' + options_panel_dvd_panel_menu_encoding_update(self) + +def options_panel_dvd_panel_menu_encoding_update(self): + if self.selected_menu_encoding == 'CBR': + self.options_panel_dvd_panel_menu_encoding_background.setPixmap(os.path.join(path_graphics, 'options_panel_dvd_encoding_cbr.png')) + self.options_panel_dvd_panel_menu_twopass_label.setShown(False) + self.options_panel_dvd_panel_menu_twopass.setShown(False) + self.options_panel_dvd_panel_menu_max_bitrate_label.setShown(False) + self.options_panel_dvd_panel_menu_max_bitrate_field.setShown(False) + self.options_panel_dvd_panel_menu_max_bitrate_field_label.setShown(False) + else: + self.options_panel_dvd_panel_menu_encoding_background.setPixmap(os.path.join(path_graphics, 'options_panel_dvd_encoding_vbr.png')) + self.options_panel_dvd_panel_menu_twopass_label.setShown(True) + self.options_panel_dvd_panel_menu_twopass.setShown(True) + self.options_panel_dvd_panel_menu_max_bitrate_label.setShown(True) + self.options_panel_dvd_panel_menu_max_bitrate_field.setShown(True) + self.options_panel_dvd_panel_menu_max_bitrate_field_label.setShown(True) + +def options_panel_dvd_panel_video_encoding_changed(self): + if self.selected_video_encoding == 'CBR': + self.selected_video_encoding = 'VBR' + else: + self.selected_video_encoding = 'CBR' + options_panel_dvd_panel_video_encoding_update(self) + +def options_panel_dvd_panel_video_encoding_update(self): + if self.selected_video_encoding == 'CBR': + self.options_panel_dvd_panel_video_encoding_background.setPixmap(os.path.join(path_graphics, 'options_panel_dvd_encoding_cbr.png')) + self.options_panel_dvd_panel_video_twopass_label.setShown(False) + self.options_panel_dvd_panel_video_twopass.setShown(False) + self.options_panel_dvd_panel_video_max_bitrate_label.setShown(False) + self.options_panel_dvd_panel_video_max_bitrate_field.setShown(False) + self.options_panel_dvd_panel_video_max_bitrate_field_label.setShown(False) + else: + self.options_panel_dvd_panel_video_encoding_background.setPixmap(os.path.join(path_graphics, 'options_panel_dvd_encoding_vbr.png')) + self.options_panel_dvd_panel_video_twopass_label.setShown(True) + self.options_panel_dvd_panel_video_twopass.setShown(True) + self.options_panel_dvd_panel_video_max_bitrate_label.setShown(True) + self.options_panel_dvd_panel_video_max_bitrate_field.setShown(True) + self.options_panel_dvd_panel_video_max_bitrate_field_label.setShown(True) + +def options_panel_dvd_panel_menu_twopass_changed(self): + self.selected_menu_twopass = not self.selected_menu_twopass + options_panel_dvd_panel_menu_twopass_update(self) + +def options_panel_dvd_panel_menu_twopass_update(self): + if self.selected_menu_twopass: + self.options_panel_dvd_panel_menu_twopass_background.setPixmap(os.path.join(path_graphics, 'options_panel_dvd_passes_two.png')) + else: + self.options_panel_dvd_panel_menu_twopass_background.setPixmap(os.path.join(path_graphics, 'options_panel_dvd_passes_one.png')) + +def options_panel_dvd_panel_video_twopass_changed(self): + self.selected_video_twopass = not self.selected_video_twopass + options_panel_dvd_panel_video_twopass_update(self) + +def options_panel_dvd_panel_video_twopass_update(self): + if self.selected_video_twopass: + self.options_panel_dvd_panel_video_twopass_background.setPixmap(os.path.join(path_graphics, 'options_panel_dvd_passes_two.png')) + else: + self.options_panel_dvd_panel_video_twopass_background.setPixmap(os.path.join(path_graphics, 'options_panel_dvd_passes_one.png')) + +def update_changes(self): + if self.options_panel_menu_buttons_edit_field.isVisible(): + edit_cancel_menu_button(self) + + self.project_name = self.nowediting_dvd_panel_project_name.text() + + if self.actual_project_file: + self.top_panel_project_name_label.setText('' + self.project_name + '
' + self.actual_project_file + '') + else: + self.top_panel_project_name_label.setText('' + self.project_name + '
Not saved') + + if self.selected_menu: + self.no_preview_label.setShown(False) + + self.menus_properties_panel_transparency_slider_value.setText(str(int(self.dict_of_menus[self.selected_menu][7]*100)) + '%') + self.menus_properties_panel_border_slider_value.setText(str(int(self.dict_of_menus[self.selected_menu][8]*100)) + '%') + + self.menus_properties_panel_transparency_slider.setValue(int(self.dict_of_menus[self.selected_menu][7]*100)) + self.menus_properties_panel_border_slider.setValue(int(self.dict_of_menus[self.selected_menu][8]*100)) + + self.menus_properties_panel_background_file_preview_background.setPixmap(os.path.join(path_tmp, self.selected_menu + '.preview.png')) + + if self.dict_of_menus[self.selected_menu][3]: + self.menus_properties_panel_overlay_file_preview_background.setPixmap(self.dict_of_menus[self.selected_menu][3]) + else: + self.menus_properties_panel_overlay_file_preview_background.setPixmap(None) + + if self.dict_of_menus[self.selected_menu][4]: + self.options_panel_menu_choose_color_button.setStyleSheet('background-color:' + self.dict_of_menus[self.selected_menu][4]) + else: + self.options_panel_menu_choose_color_button.setStyleSheet('background-color:white') + + if self.dict_of_menus[self.selected_menu][0].split('.')[-1] == 'png': + self.menus_properties_panel_sound_box.setShown(True) + self.menus_properties_panel_sound_label.setShown(True) + self.menus_properties_panel_sound_open_button.setShown(True) + + if self.dict_of_menus[self.selected_menu][5]: + self.menus_properties_panel_sound_label.setText('' + self.dict_of_menus[self.selected_menu][5].split('/')[-1].split('\\')[-1] + '') + else: + self.menus_properties_panel_sound_label.setText('' + 'No selected audio' + '') + else: + self.menus_properties_panel_sound_box.setShown(False) + self.menus_properties_panel_sound_label.setShown(False) + self.menus_properties_panel_sound_open_button.setShown(False) + + if self.dict_of_menus[self.selected_menu][6]: + self.menus_properties_panel_main_menu_checkbox_background.setPixmap(os.path.join(path_graphics, 'menus_properties_panel_main_menu_checkbox_checked.png')) + else: + self.menus_properties_panel_main_menu_checkbox_background.setPixmap(os.path.join(path_graphics, 'menus_properties_panel_main_menu_checkbox_unchecked.png')) + + if self.overlay_preview: + self.menus_properties_panel_overlay_preview_background.setPixmap(os.path.join(path_graphics, 'menus_properties_panel_preview_checked.png')) + else: + self.menus_properties_panel_overlay_preview_background.setPixmap(os.path.join(path_graphics, 'menus_properties_panel_preview_unchecked.png')) + + if self.directions_preview: + self.menus_properties_panel_directions_preview_background.setPixmap(os.path.join(path_graphics, 'menus_properties_panel_preview_checked.png')) + else: + self.menus_properties_panel_directions_preview_background.setPixmap(os.path.join(path_graphics, 'menus_properties_panel_preview_unchecked.png')) + + if self.selected_menu_button: + self.options_panel_menu_buttons_x_position.setValue(self.dict_of_menus[self.selected_menu][2][self.selected_menu_button][0]) + self.options_panel_menu_buttons_y_position.setValue(self.dict_of_menus[self.selected_menu][2][self.selected_menu_button][1]) + self.options_panel_menu_buttons_width.setValue(self.dict_of_menus[self.selected_menu][2][self.selected_menu_button][2]) + self.options_panel_menu_buttons_height.setValue(self.dict_of_menus[self.selected_menu][2][self.selected_menu_button][3]) + + populate_jumpto(self) + + if self.dict_of_menus[self.selected_menu][2][self.selected_menu_button][4]: + self.options_panel_menu_buttons_jumpto.setCurrentIndex(self.options_panel_menu_buttons_jumpto.findText(self.dict_of_menus[self.selected_menu][2][self.selected_menu_button][4])) + else: + self.options_panel_menu_buttons_jumpto.setCurrentIndex(-1) + + populate_button_directions_list(self) + + if self.dict_of_menus[self.selected_menu][2][self.selected_menu_button][5][0]: + self.options_panel_menu_buttons_directions_top.setCurrentIndex(self.options_panel_menu_buttons_directions_top.findText(self.dict_of_menus[self.selected_menu][2][self.selected_menu_button][5][0])) + else: + self.options_panel_menu_buttons_directions_top.setCurrentIndex(0) + + if self.dict_of_menus[self.selected_menu][2][self.selected_menu_button][5][1]: + self.options_panel_menu_buttons_directions_right.setCurrentIndex(self.options_panel_menu_buttons_directions_right.findText(self.dict_of_menus[self.selected_menu][2][self.selected_menu_button][5][1])) + else: + self.options_panel_menu_buttons_directions_right.setCurrentIndex(0) + + if self.dict_of_menus[self.selected_menu][2][self.selected_menu_button][5][2]: + self.options_panel_menu_buttons_directions_bottom.setCurrentIndex(self.options_panel_menu_buttons_directions_bottom.findText(self.dict_of_menus[self.selected_menu][2][self.selected_menu_button][5][2])) + else: + self.options_panel_menu_buttons_directions_bottom.setCurrentIndex(0) + + if self.dict_of_menus[self.selected_menu][2][self.selected_menu_button][5][3]: + self.options_panel_menu_buttons_directions_left.setCurrentIndex(self.options_panel_menu_buttons_directions_left.findText(self.dict_of_menus[self.selected_menu][2][self.selected_menu_button][5][3])) + else: + self.options_panel_menu_buttons_directions_left.setCurrentIndex(0) + + if self.nowediting == 'menus' and not self.nowediting_panel.y() == -40: #self.menus_properties_panel.y() == self.main_panel.height() and + generate_effect(self, self.menus_properties_panel_animation, 'geometry', 500, [self.menus_properties_panel.x(),self.menus_properties_panel.y(),self.menus_properties_panel.width(),self.menus_properties_panel.height()], [self.menus_properties_panel.x(),self.main_panel.height()-125,self.menus_properties_panel.width(),self.menus_properties_panel.height()]) + generate_effect(self, self.options_panel_animation, 'geometry', 500, [self.options_panel.x(),self.options_panel.y(),self.options_panel.width(),self.options_panel.height()], [820,self.options_panel.y(),self.options_panel.width(),self.options_panel.height()]) + elif self.nowediting == 'menus' and self.nowediting_panel.y() == 80: + generate_effect(self, self.menus_properties_panel_animation, 'geometry', 500, [self.menus_properties_panel.x(),self.menus_properties_panel.y(),self.menus_properties_panel.width(),self.menus_properties_panel.height()], [self.menus_properties_panel.x(),self.main_panel.height(),self.menus_properties_panel.width(),self.menus_properties_panel.height()]) + + if len(self.list_of_menus) == 1: + self.menus_properties_panel_main_menu_checkbox.setShown(False) + else: + self.menus_properties_panel_main_menu_checkbox.setShown(True) + + if self.selected_video: + populate_chapters_list(self) + if not self.selected_video_chapter: + self.options_panel_video_chapters_remove.setEnabled(False) + self.options_panel_video_chapters_edit.setEnabled(False) + + if self.nowediting == 'videos' and self.videos_player_panel.y() == self.main_panel.height(): + generate_effect(self, self.videos_player_panel_animation, 'geometry', 500, [self.videos_player_panel.x(),self.videos_player_panel.y(),self.videos_player_panel.width(),self.videos_player_panel.height()], [self.videos_player_panel.x(),self.main_panel.height()-125,self.videos_player_panel.width(),self.videos_player_panel.height()]) + populate_jumpto_list(self) + if self.dict_of_videos[self.selected_video][6]: + self.options_panel_video_jumpto.setCurrentIndex(self.options_panel_video_jumpto.findText(self.dict_of_videos[self.selected_video][6])) + else: + self.options_panel_video_jumpto.setCurrentIndex(self.options_panel_video_jumpto.findText('Main menu')) + + self.options_panel_video_intro_video_checkbox.setChecked(self.dict_of_videos[self.selected_video][3]) + self.options_panel_video_reencode_video_checkbox.setChecked(self.dict_of_videos[self.selected_video][4]) + self.options_panel_video_resolution_combo.setEnabled(self.dict_of_videos[self.selected_video][4]) + self.options_panel_video_resolution_combo.setCurrentIndex(self.dict_of_videos[self.selected_video][7]) + + if ((not self.has_menus) or (self.has_menus and len(self.list_of_menus) > 0)) and len(self.list_of_videos) > 0: + generate_effect(self, self.finalize_panel_animation, 'geometry', 500, [self.finalize_panel.x(),self.finalize_panel.y(),self.finalize_panel.width(),self.finalize_panel.height()], [self.main_panel.width() - 370,self.finalize_panel.y(),self.finalize_panel.width(),self.finalize_panel.height()]) + else: + generate_effect(self, self.finalize_panel_animation, 'geometry', 500, [self.finalize_panel.x(),self.finalize_panel.y(),self.finalize_panel.width(),self.finalize_panel.height()], [self.main_panel.width(),self.finalize_panel.y(),self.finalize_panel.width(),self.finalize_panel.height()]) + + self.options_panel_dvd_panel_dvd_image.update() + + estimated_size = 0.0 + estimated_proportion = 0 + + if len(self.list_of_videos) > 0: + if self.has_menus and len(self.list_of_menus) > 0: + for menu in self.list_of_menus: + estimated_size += float(((self.selected_menu_bitrate + int(self.selected_audio_datarate.split(' ')[0]))*.001) * self.dict_of_menus[menu][9]) + for video in self.list_of_videos: + estimated_size += float(((self.selected_video_bitrate + int(self.selected_audio_datarate.split(' ')[0]))*.001) * self.dict_of_videos[video][5]) + estimated_proportion = int(estimated_size / 360) + + final_text = 'ESTIMATED SIZE:
' + if estimated_size*.000125 < 1.0: + final_text += str("%.2f" % round(estimated_size*.125,2)) + ' MB' + else: + final_text += str("%.2f" % round(estimated_size/8590.0,2)) + ' GB' + final_text += ' (' + str(estimated_proportion) + '%)' + + self.options_panel_dvd_panel_size_info.setText(final_text) + + self.options_panel_dvd_panel_menu_bitrate_field.setValue(self.selected_menu_bitrate) + self.options_panel_dvd_panel_menu_max_bitrate_field.setValue(self.selected_menu_max_bitrate) + self.options_panel_dvd_panel_video_bitrate_field.setValue(self.selected_video_bitrate) + self.options_panel_dvd_panel_video_max_bitrate_field.setValue(self.selected_video_max_bitrate) + self.options_panel_dvd_panel_gop.setCurrentIndex(self.options_panel_dvd_panel_gop.findText(str(self.selected_gop_size))) + self.options_panel_dvd_panel_audio_datarate.setCurrentIndex(self.options_panel_dvd_panel_audio_datarate.findText(self.selected_audio_datarate)) + + self.preview.update() + +def main_tabs_changed(self): + if self.nowediting == 'menus': + self.options_panel_menu_panel_0.setShown(False) + self.options_panel_menu_buttons_panel_0.setShown(False) + self.options_panel_video_panel.setShown(True) + self.options_panel_video_chapters_panel_0.setShown(True) + self.preview_video_widget.setShown(False) + self.preview_video_play_button.setShown(False) + self.preview_video_pause_button.setShown(False) + self.preview_video_stop_button.setShown(False) + self.preview_video_seek_back_frame_button.setShown(False) + self.preview_video_seek_next_frame_button.setShown(False) + self.preview_video_add_this_mark_button.setShown(False) + self.menus_properties_panel_overlay_preview_button.setShown(True) + #if not self.selected_menu: + clean_menus_list_selection(self) + self.selected_video = None + elif self.nowediting == 'videos': + self.options_panel_menu_panel_0.setShown(True) + self.options_panel_menu_buttons_panel_0.setShown(True) + self.options_panel_video_panel.setShown(False) + self.options_panel_video_chapters_panel_0.setShown(False) + self.preview_video_play_button.setShown(True) + self.preview_video_pause_button.setShown(True) + self.preview_video_stop_button.setShown(True) + self.preview_video_seek_back_frame_button.setShown(True) + self.preview_video_seek_next_frame_button.setShown(True) + self.preview_video_add_this_mark_button.setShown(True) + self.menus_properties_panel_overlay_preview_button.setShown(False) + #if not self.selected_video: + clean_videos_list_selection(self) + #else: + if self.selected_video: + if self.preview_video_obj.state() == Phonon.PlayingState: + self.preview_video_obj.stop() + self.preview_video_widget.setShown(True) + self.selected_menu = None + +def change_aspect_ratio(self): + for menu in self.list_of_menus: + generate_preview_image(self, menu, self.dict_of_menus) + + for video in self.list_of_videos: + generate_preview_image(self, video, self.dict_of_videos) + + if self.selected_aspect_ratio == 0: + self.preview.setGeometry(50, 220, 720, 405) + self.preview_video_widget.setGeometry(50, 180, 720, 405) + self.nowediting_menus_panel_list.setIconSize(QtCore.QSize(100, 56)) + self.nowediting_videos_panel_list.setIconSize(QtCore.QSize(100, 56)) + self.options_panel_menu_buttons_x_position.setMaximum(720) + self.options_panel_menu_buttons_width.setMaximum(720) + self.menus_properties_panel_background_file_preview.setGeometry(10,50,89,50) + self.menus_properties_panel_background_file_preview_background.setGeometry(0,0,self.menus_properties_panel_background_file_preview.width(),self.menus_properties_panel_background_file_preview.height()) + self.menus_properties_panel_background_file_preview_foreground.setGeometry(0,0,self.menus_properties_panel_background_file_preview.width(),self.menus_properties_panel_background_file_preview.height()) + self.menus_properties_panel_background_file_preview_foreground.setPixmap(os.path.join(path_graphics, 'menus_properties_panel_background_file_preview_foreground_16_9.png')) + self.menus_properties_panel_overlay_file_preview.setGeometry(110,50,89,50) + self.menus_properties_panel_overlay_file_preview_background.setGeometry(0,0,self.menus_properties_panel_overlay_file_preview.width(),self.menus_properties_panel_overlay_file_preview.height()) + self.menus_properties_panel_overlay_file_preview_foreground.setGeometry(0,0,self.menus_properties_panel_overlay_file_preview.width(),self.menus_properties_panel_overlay_file_preview.height()) + self.menus_properties_panel_overlay_file_preview_foreground.setPixmap(os.path.join(path_graphics, 'menus_properties_panel_background_file_preview_foreground_16_9.png')) + elif self.selected_aspect_ratio == 1: + self.preview.setGeometry(90, 220, 640, 480) + self.preview_video_widget.setGeometry(90, 180, 640, 480) + self.nowediting_menus_panel_list.setIconSize(QtCore.QSize(88, 66)) + self.nowediting_videos_panel_list.setIconSize(QtCore.QSize(88, 66)) + self.options_panel_menu_buttons_x_position.setMaximum(640) + self.options_panel_menu_buttons_width.setMaximum(640) + self.menus_properties_panel_background_file_preview.setGeometry(10,50,67,50) + self.menus_properties_panel_background_file_preview_background.setGeometry(0,0,self.menus_properties_panel_background_file_preview.width(),self.menus_properties_panel_background_file_preview.height()) + self.menus_properties_panel_background_file_preview_foreground.setGeometry(0,0,self.menus_properties_panel_background_file_preview.width(),self.menus_properties_panel_background_file_preview.height()) + self.menus_properties_panel_background_file_preview_foreground.setPixmap(os.path.join(path_graphics, 'menus_properties_panel_background_file_preview_foreground_4_3.png')) + self.menus_properties_panel_overlay_file_preview.setGeometry(110,50,67,50) + self.menus_properties_panel_overlay_file_preview_background.setGeometry(0,0,self.menus_properties_panel_overlay_file_preview.width(),self.menus_properties_panel_overlay_file_preview.height()) + self.menus_properties_panel_overlay_file_preview_foreground.setGeometry(0,0,self.menus_properties_panel_overlay_file_preview.width(),self.menus_properties_panel_overlay_file_preview.height()) + self.menus_properties_panel_overlay_file_preview_foreground.setPixmap(os.path.join(path_graphics, 'menus_properties_panel_background_file_preview_foreground_4_3.png')) + + self.options_panel_menu_buttons_y_position.setMaximum(int(self.video_formats[self.selected_video_format].split(' ')[1].split('x')[1])) + self.options_panel_menu_buttons_height.setMaximum(int(self.video_formats[self.selected_video_format].split(' ')[1].split('x')[1])) + + self.no_preview_label.setGeometry(0,0,self.preview.width(),self.preview.height()) + + if self.selected_menu: + update_overlay_image_preview(self) + + populate_menus_list(self) + populate_videos_list(self) + + update_changes(self) + +def convert_to_timecode(value, framerate): + value = value.replace('s', '') + framerate = framerate.replace('s','') + + framerate = float(framerate.split('/')[1])/float(framerate.split('/')[0]) + + if '/' in value: + value = float(value.split('/')[0])/float(value.split('/')[1]) + else: + value = float(value) + + value = value/framerate + + fr = int(str('%03d' % int(str(value).split('.')[1]))[:3]) + mm, ss = divmod(value, 60) + hh, mm = divmod(mm, 60) + + return '%02d:%02d:%02d.%03d' % (hh, mm, ss, fr) + +def convert_timecode_to_miliseconds(timecode): + final_value = 0 + final_value += int(timecode.split(':')[2].split('.')[0])*1000 + final_value += int(timecode.split(':')[1])*60000 + final_value += int(timecode.split(':')[0])*3600000 + final_value += int(timecode.split('.')[-1]) + return final_value + +def sort_list_of_chapters(dict_of_chapters): + + dict_of_chapters_for_order = {} + for name in dict_of_chapters.keys(): + dict_of_chapters_for_order[dict_of_chapters[name]] = name + list_of_chapters_in_order = sorted(dict_of_chapters_for_order.keys()) + + new_list = [] + for timecode in list_of_chapters_in_order: + new_list.append(dict_of_chapters_for_order[timecode]) + + return new_list + +def set_generate_dvd_kind(self): + if not self.finalize_panel_generate_button_iso_checkbox.isChecked() and not self.finalize_panel_generate_button_ddp_checkbox.isChecked(): + self.finalize_panel_generate_button_iso_checkbox.setChecked(True) + +################################################################################################### +############################################################################################# MENUS +################################################################################################### + +def set_main_menu(self): + self.dict_of_menus[self.selected_menu][6] = not self.dict_of_menus[self.selected_menu][6] + + for menu in self.list_of_menus: + if not menu == self.selected_menu: + self.dict_of_menus[menu][6] = False + + update_changes(self) + +def choose_color(self): + color = QtGui.QColorDialog().getColor() + if color.isValid(): + self.dict_of_menus[self.selected_menu][4] = color.name() + preview_overlay(self) + update_changes(self) + + +def generate_preview_image(self, image_item, image_dict): + if image_dict[image_item][0].split('.')[-1] in ['mov', 'm4v', 'mpg', 'm2v', 'mp4']: + subprocess.call([ffmpeg_bin, '-loglevel', 'error', '-y', '-ss', '00:03.00', '-i', get_preview_file(self, image_dict[image_item][0]), '-frames:v', '1', os.path.join(path_tmp, image_item + '.preview_.png')]) + image_path = os.path.join(path_tmp, image_item + '.preview_.png') + else: + image_path = get_preview_file(self, image_dict[image_item][0]) + + if self.selected_aspect_ratio == 0: + size = '720x405!' + elif self.selected_aspect_ratio == 1: + size = '640x480!' + subprocess.call([imagemagick_convert_bin, get_preview_file(self, image_path), '-resize', size, os.path.join(path_tmp, image_item + '.preview.png')]) + +def menu_selected(self): + if self.nowediting_menus_panel_list.currentItem(): + self.nowediting_menus_panel_remove.setEnabled(True) + self.selected_menu = self.nowediting_menus_panel_list.currentItem().text().split('\n')[0] + else: + self.nowediting_menus_panel_remove.setEnabled(False) + + populate_menu_buttons_list(self) + + + self.selected_menu_button = None + self.options_panel_menu_buttons_position_box.setEnabled(False) + self.options_panel_menu_buttons.setCurrentItem(None) + + self.preview_video_widget.setShown(False) + + nowediting_panel_button_changed(self, self.nowediting) + populate_menu_buttons_list(self) + clean_buttons_selection(self) + update_changes(self) + +def add_menu(self): + image_path_list = QtGui.QFileDialog.getOpenFileName(self, 'Select the image or video for menu', path_home, 'PNG, JPEG images or MPEG videos (*.jpg *.png *.m4v *.m2v *.mpg *.mp4 *.mov)')[0]#.toUtf8() + + for image_path_file in image_path_list: + image_path = os.path.abspath(image_path_file) + if not image_path == '': + menu_name = check_name(self, self.list_of_menus, image_path.split('/')[-1].split('\\')[-1].split('.')[0]) + + if len(self.list_of_menus) > 0: + mainmenu = False + else: + mainmenu = True + length = 60.0 + if image_path.endswith('.jpg') or image_path.endswith('.png') or image_path.endswith('.jpeg'): + length = 60.0 + else: + length_xml = unicode(subprocess.Popen([ffprobe_bin, '-loglevel', 'error', '-show_format', '-print_format', 'xml', image_path], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.read(), 'utf-8') + length = float(length_xml.split(' duration="')[1].split('"')[0]) + + self.list_of_menus.append(menu_name) + self.dict_of_menus[menu_name] = [ image_path, # [0] Arquivo do fundo, imagem ou video + [], # [1] Lista de botoes + {}, # [2] Dicionario de botoes + None, # [3] Arquivo de overlay (str) + None, # [4] Cor do Overlay (str) + None, # [5] Arquivo de som (str) + mainmenu, # [6] Se é o menu principal + .5, # [7] Transparencia + .5, # [8] Borda dura + length # [9] Duracao em segundos + ] + + generate_preview_image(self, menu_name, self.dict_of_menus) + + self.selected_menu_button = None + clean_menus_list_selection(self) + + self.selected_menu = self.list_of_menus[-1] + update_changes(self) + populate_menus_list(self) + + nowediting_panel_button_changed(self, self.nowediting) + +def check_name(self, names_list, name): + final_name = name + counter = 1 + while final_name in names_list: + final_name = name + '_' + str(counter) + counter += 1 + else: + return final_name + +def populate_menus_list(self): + self.nowediting_menus_panel_list.clear() + for menu in self.list_of_menus: + icon = QtGui.QIcon(os.path.join(path_tmp, menu + '.preview.png')) + self.nowediting_menus_panel_list.addItem(QtGui.QListWidgetItem(icon, menu)) + + +def select_menu_file(self): + image_path = QtGui.QFileDialog.getOpenFileName(self, 'Select the image or video for menu', path_home, 'PNG, JPEG images or MPEG videos (*.jpg *.png *.m4v *.m2v *.mpg *.mp4 *.mov)')[0]#.toUtf8() + if not image_path == '': + self.dict_of_menus[self.selected_menu][0] = image_path + + generate_preview_image(self, self.selected_menu, self.dict_of_menus) + populate_menus_list(self) + update_changes(self) + + +def select_overlay_file(self): + overlay_image_path = QtGui.QFileDialog.getOpenFileName(self, "Select an image for the overlay", path_home, "Images (*.jpg *.png)")[0]#.toUtf8() + if not overlay_image_path == '': + self.dict_of_menus[self.selected_menu][3] = overlay_image_path + update_overlay_image_preview(self) + + +def update_overlay_image_preview(self): + preview_overlay(self) + update_changes(self) + +def preview_overlay_clicked(self): + self.overlay_preview = not self.overlay_preview + preview_overlay(self) + +def preview_overlay(self): + if self.selected_aspect_ratio == 0: + size = '720x405!' + elif self.selected_aspect_ratio == 1: + size = '640x480!' + + for menu in self.list_of_menus: + if self.dict_of_menus[menu][3]: + menu_color = '#FFFFFF' + if self.dict_of_menus[menu][4]: + menu_color = self.dict_of_menus[menu][4] + subprocess.call([imagemagick_convert_bin, get_preview_file(self, self.dict_of_menus[menu][3]), '-resize', size, '+antialias', '-threshold', str(int(self.dict_of_menus[menu][8]*100)) + '%', '-flatten', os.path.join(path_tmp, self.dict_of_menus[menu][3].split('/')[-1].split('\\')[-1][:-4] + '_hl.preview.png')]) + subprocess.call([imagemagick_convert_bin, os.path.join(path_tmp, self.dict_of_menus[menu][3].split('/')[-1].split('\\')[-1][:-4] + '_hl.preview.png'), '-threshold', str(int(self.dict_of_menus[menu][8]*100)) + '%', '-transparent', 'white', '-channel', 'RGBA', '-fill', menu_color + str('%02x' % int(self.dict_of_menus[menu][7]*255)), '-opaque', 'black', os.path.join(path_tmp, self.dict_of_menus[menu][3].split('/')[-1].split('\\')[-1][:-4] + '_hl.preview.png')]) + + update_changes(self) + +def preview_directions(self): + self.directions_preview = not self.directions_preview + update_changes(self) + +def select_menu_sound_file(self): + menu_sound_path = QtGui.QFileDialog.getOpenFileName(self, "Select an audio file", path_home, "Audio file (*.ac3 *.flac)")[0] + if not menu_sound_path == '': + self.dict_of_menus[self.selected_menu][5] = menu_sound_path + self.menus_properties_panel_sound_label.setText(menu_sound_path.split('/')[-1].split('\\')[-1]) + +def remove_menu(self): + self.list_of_menus.remove(self.selected_menu) + del self.dict_of_menus[self.selected_menu] + + if len(self.list_of_menus) == 1: + self.dict_of_menus[self.list_of_menus[0]][6] = True + + for menu in self.list_of_menus: + for button in self.dict_of_menus[menu][1]: + print self.dict_of_menus[menu][2][button][4] + if self.dict_of_menus[menu][2][button][4] == self.selected_menu: + self.dict_of_menus[menu][2][button][4] = None + + clean_menus_list_selection(self) + populate_menus_list(self) + update_changes(self) + +def clean_menus_list_selection(self): + self.selected_menu = None + self.no_preview_label.setShown(True) + self.nowediting_menus_panel_list.setCurrentItem(None) + clean_buttons_selection(self) + + + +def transparency_slider_changing(self): + self.menus_properties_panel_transparency_slider_value.setText(str(int(self.menus_properties_panel_transparency_slider.value())) + '%') + +def transparency_slider_changed(self): + self.dict_of_menus[self.selected_menu][7] = self.menus_properties_panel_transparency_slider.value()/100.0 + preview_overlay(self) + +def border_slider_changing(self): + self.menus_properties_panel_border_slider_value.setText(str(int(self.menus_properties_panel_border_slider.value())) + '%') + +def border_slider_changed(self): + self.dict_of_menus[self.selected_menu][8] = self.menus_properties_panel_border_slider.value()/100.0 + preview_overlay(self) + +################################################################################################### +########################################################################################### BUTTONS +################################################################################################### + +def add_menu_button(self): + new_button_name = check_name(self, self.dict_of_menus[self.selected_menu][1], 'button') + self.dict_of_menus[self.selected_menu][1].append(new_button_name) + self.dict_of_menus[self.selected_menu][2][new_button_name] = [ 10, # posição X + 10, # posição Y + 50, # largura + 50, # altura + None, # jump to + [ None, # top direction + None, # right direction + None, # bottom direction + None # left direction + ] + ] + populate_menu_buttons_list(self) + update_jumpto_list(self) + update_changes(self) + +def menu_button_selected(self): + self.options_panel_menu_buttons_position_box.setEnabled(True) + self.selected_menu_button = self.options_panel_menu_buttons.currentItem().text() + self.options_panel_menu_buttons_remove.setEnabled(True) + self.options_panel_menu_buttons_edit.setEnabled(True) + update_changes(self) + +def menu_buttons_set_geometry(self): + final_list = [self.options_panel_menu_buttons_x_position.value(), self.options_panel_menu_buttons_y_position.value(), self.options_panel_menu_buttons_width.value(), self.options_panel_menu_buttons_height.value(), self.dict_of_menus[self.selected_menu][2][self.selected_menu_button][4], self.dict_of_menus[self.selected_menu][2][self.selected_menu_button][5]] + self.dict_of_menus[self.selected_menu][2][self.selected_menu_button] = final_list + update_changes(self) + +def populate_menu_buttons_list(self): + self.options_panel_menu_buttons.clear() + self.options_panel_menu_buttons_edit.setText('') + for button in self.dict_of_menus[self.selected_menu][1]: + self.options_panel_menu_buttons.addItem(button) + +def populate_button_directions_list(self): + final_list = ["Auto"] + for button in self.dict_of_menus[self.selected_menu][1]: + if not button == self.selected_menu_button: + final_list.append(button) + self.options_panel_menu_buttons_directions_top.clear() + self.options_panel_menu_buttons_directions_top.addItems(final_list) + self.options_panel_menu_buttons_directions_right.clear() + self.options_panel_menu_buttons_directions_right.addItems(final_list) + self.options_panel_menu_buttons_directions_bottom.clear() + self.options_panel_menu_buttons_directions_bottom.addItems(final_list) + self.options_panel_menu_buttons_directions_left.clear() + self.options_panel_menu_buttons_directions_left.addItems(final_list) + +def remove_menu_button(self): + del self.dict_of_menus[self.selected_menu][2][self.selected_menu_button] + self.dict_of_menus[self.selected_menu][1].remove(self.selected_menu_button) + + for menu in self.list_of_menus: + for button in self.dict_of_menus[menu][1]: + directions_list = self.dict_of_menus[menu][2][button][5] + for i in range(len(directions_list)): + if directions_list[i] == self.selected_menu_button: + directions_list[i] = None + self.dict_of_menus[menu][2][button][5] = directions_list + + populate_menu_buttons_list(self) + clean_buttons_selection(self) + +def edit_menu_button(self): + self.options_panel_menu_buttons.setEnabled(False) + self.options_panel_menu_buttons_remove.setEnabled(False) + self.options_panel_menu_buttons_add.setEnabled(False) + self.options_panel_menu_buttons_position_box.setEnabled(False) + self.options_panel_menu_buttons_edit_field.setVisible(True) + self.options_panel_menu_buttons_edit_confirm.setVisible(True) + self.options_panel_menu_buttons_edit_cancel.setVisible(True) + self.options_panel_menu_buttons_edit.setText(self.selected_menu_button) + + self.options_panel_menu_buttons_edit_field + +def edit_field_menu_changed(self): + if self.options_panel_menu_buttons_edit_field.text() in self.dict_of_menus[self.selected_menu][1]: + self.options_panel_menu_buttons_edit_confirm.setEnabled(False) + else: + self.options_panel_menu_buttons_edit_confirm.setEnabled(True) + +def edit_confirm_menu_button(self): + old_menu_button_name = self.selected_menu_button + old_menu_button = self.dict_of_menus[self.selected_menu][2][self.selected_menu_button] + self.dict_of_menus[self.selected_menu][2][self.options_panel_menu_buttons_edit_field.text()] = old_menu_button + self.dict_of_menus[self.selected_menu][1].append(self.options_panel_menu_buttons_edit_field.text()) + + del self.dict_of_menus[self.selected_menu][2][old_menu_button_name] + self.dict_of_menus[self.selected_menu][1].remove(old_menu_button_name) + + self.dict_of_menus[self.selected_menu][1] + + for button in self.dict_of_menus[self.selected_menu][1]: + direction_index = 0 + for direction in self.dict_of_menus[self.selected_menu][2][button][5]: + if direction == old_menu_button_name: + self.dict_of_menus[self.selected_menu][2][button][5][direction_index] = self.options_panel_menu_buttons_edit_field.text() + direction_index += 1 + + populate_menu_buttons_list(self) + clean_buttons_selection(self) + +def edit_cancel_menu_button(self): + self.options_panel_menu_buttons_edit_field.setVisible(False) + self.options_panel_menu_buttons_edit_confirm.setVisible(False) + self.options_panel_menu_buttons_edit_cancel.setVisible(False) + populate_menu_buttons_list(self) + clean_buttons_selection(self) + +def clean_buttons_selection(self): + self.options_panel_menu_buttons.setEnabled(True) + self.options_panel_menu_buttons_add.setEnabled(True) + self.options_panel_menu_buttons_edit_field.setText('') + self.selected_menu_button = None + self.options_panel_menu_buttons.setCurrentItem(None) + self.options_panel_menu_buttons_remove.setEnabled(False) + self.options_panel_menu_buttons_position_box.setEnabled(False) + self.options_panel_menu_buttons_edit.setEnabled(False) + self.options_panel_menu_buttons_x_position.setValue(0) + self.options_panel_menu_buttons_y_position.setValue(0) + self.options_panel_menu_buttons_width.setValue(0) + self.options_panel_menu_buttons_height.setValue(0) + update_changes(self) + +def button_directions_selected(self): + directions_list = [None,None,None,None] + if not self.options_panel_menu_buttons_directions_top.currentText() == 'Auto': + directions_list[0] = self.options_panel_menu_buttons_directions_top.currentText() + if not self.options_panel_menu_buttons_directions_right.currentText() == 'Auto': + directions_list[1] = self.options_panel_menu_buttons_directions_right.currentText() + if not self.options_panel_menu_buttons_directions_bottom.currentText() == 'Auto': + directions_list[2] = self.options_panel_menu_buttons_directions_bottom.currentText() + if not self.options_panel_menu_buttons_directions_left.currentText() == 'Auto': + directions_list[3] = self.options_panel_menu_buttons_directions_left.currentText() + self.dict_of_menus[self.selected_menu][2][self.selected_menu_button][5] = directions_list + update_changes(self) + +################################################################################################### +############################################################################################ VIDEOS +################################################################################################### + +def update_timeline(self): + #self.videos_player_controls_panel_current_time.setText('' + convert_to_timecode(str(self.preview_video_obj.currentTime()),'1/1000') + '') + self.videos_player_controls_panel_current_time.setText(convert_to_timecode(str(self.preview_video_obj.currentTime()),'1/1000')) + self.videos_player_timeline.update() + +def add_video(self): + video_path_list = QtGui.QFileDialog.getOpenFileNames(self, "Selecione um video", path_home, "Video files (*.m4v *.m2v *.mpg *.mp4 *.mov)")[0] + + for video_path_file in video_path_list: + video_path = os.path.abspath(video_path_file) + if not video_path == '': + video_name = video_path.split('/')[-1].split('\\')[-1].split('.')[0] + + chapters_list, chapters_dict = get_video_chapters(self, video_path) + + length_xml = unicode(subprocess.Popen([ffprobe_bin, '-loglevel', 'error', '-show_format', '-print_format', 'xml', video_path], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.read(), 'utf-8') + length = float(length_xml.split(' duration="')[1].split('"')[0]) + + self.dict_of_videos[video_name] = [ video_path, # [0] Caminho do video + chapters_list, # [1] Lista de capítulos + chapters_dict, # [2] Dict de capítulos + False, # [3] se é o video de intro + True, # [4] se é para ser reconvertido + length, # [5] Duração + None, # [6] Post + 0 # [7] Resolução + ] + self.list_of_videos.append(video_name) + + generate_preview_image(self, video_name, self.dict_of_videos) + + populate_videos_list(self) + +def populate_videos_list(self): + self.nowediting_videos_panel_list.clear() + for video in self.list_of_videos: + icon = QtGui.QIcon(os.path.join(path_tmp, video + '.preview.png')) + self.nowediting_videos_panel_list.addItem(QtGui.QListWidgetItem(icon, video)) + +def update_jumpto_list(self): + self.list_of_jumpto = [] + for video in self.dict_of_videos.keys(): + self.list_of_jumpto.append(video) + for menu in self.list_of_menus: + self.list_of_jumpto.append(menu) + +def remove_video(self): + del self.dict_of_videos[self.selected_video] + self.list_of_videos.remove(self.selected_video) + + for menu in self.list_of_menus: + for button in self.dict_of_menus[menu][1]: + if self.dict_of_menus[menu][2][button][4] == self.selected_video: + self.dict_of_menus[menu][2][button][4] = None + + clean_videos_list_selection(self) + populate_videos_list(self) + +def clean_videos_list_selection(self): + self.selected_video = None + self.no_preview_label.setShown(True) + self.nowediting_videos_panel_list.setCurrentItem(None) + +def video_selected(self): + if self.nowediting_videos_panel_list.currentItem(): + self.nowediting_videos_panel_remove.setEnabled(True) + self.selected_video = self.nowediting_videos_panel_list.currentItem().text() + else: + self.nowediting_videos_panel_remove.setEnabled(False) + + + self.preview_video_widget.setShown(True) + self.preview_video_obj.setCurrentSource(Phonon.MediaSource(get_preview_file(self, self.dict_of_videos[self.selected_video][0]))) + + nowediting_panel_button_changed(self, self.nowediting) + + update_changes(self) + +def button_jumpto_selected(self): + self.dict_of_menus[self.selected_menu][2][self.selected_menu_button][4] = self.options_panel_menu_buttons_jumpto.currentText() + +def video_play(self): + self.preview_video_obj.play() + +def video_pause(self): + self.videos_player_controls_panel_pause_background.setPixmap(os.path.join(path_graphics, 'videos_player_controls_panel_pause_press.png')) + self.videos_player_controls_panel_play_background.setPixmap(os.path.join(path_graphics, 'videos_player_controls_panel_play_press.png')) + self.preview_video_obj.pause() + +def video_stop(self): + self.preview_video_obj.stop() + update_timeline(self) + +def video_seek_next_frame(self, position): + self.preview_video_obj.seek(self.preview_video_obj.currentTime() + position) + update_timeline(self) + +def video_seek_back_frame(self, position): + self.preview_video_obj.seek(self.preview_video_obj.currentTime() - position) + update_timeline(self) + +def video_add_this_mark_frame(self): + self.selected_video_chapter = None + append_chapter(self, check_name(self, self.dict_of_videos[self.selected_video][1], 'mark'), convert_to_timecode(str(self.preview_video_obj.currentTime()), '1/1000')) + update_changes(self) + +def populate_jumpto(self): + self.options_panel_menu_buttons_jumpto.clear() + final_list = [] + for menu in self.list_of_menus: + final_list.append(menu) + for video in self.list_of_videos: + final_list.append(video) + for chapter in sort_list_of_chapters(self.dict_of_videos[video][2]): + final_list.append(video + ' > ' + str(chapter) + ' (' + self.dict_of_videos[video][2][chapter] + ')') + list_of_chapter_groups = [] + for chapter in sort_list_of_chapters(self.dict_of_videos[video][2]): + if not str(chapter).split(' ')[0] in list_of_chapter_groups: + list_of_chapter_groups.append(str(chapter).split(' ')[0]) + final_list.append(video + ' > ' + str(chapter).split(' ')[0]) + self.options_panel_menu_buttons_jumpto.addItems(final_list) + +def set_intro_video(self): + self.dict_of_videos[self.selected_video][3] = self.options_panel_video_intro_video_checkbox.isChecked() + + for video in self.list_of_videos: + if not video == self.selected_video: + self.dict_of_videos[video][3] = False + +def set_reencode_video(self): + self.dict_of_videos[self.selected_video][4] = self.options_panel_video_reencode_video_checkbox.isChecked() + update_changes(self) + +def video_resolution_combo_selected(self): + self.dict_of_videos[self.selected_video][7] = self.options_panel_video_resolution_combo.currentIndex() + +def video_jumpto_selected(self): + if self.options_panel_video_jumpto.currentText() == 'Main menu': + self.dict_of_videos[self.selected_video][6] = None + else: + self.dict_of_videos[self.selected_video][6] = self.options_panel_video_jumpto.currentText() + +def populate_jumpto_list(self): + final_list = ['Main menu'] + final_list += self.list_of_menus + final_list += self.list_of_videos + final_list.remove(self.selected_video) + self.options_panel_video_jumpto.clear() + self.options_panel_video_jumpto.addItems(final_list) + +################################################################################################### +########################################################################################## CHAPTERS +################################################################################################### + +def import_chapters(self): + filepath = QtGui.QFileDialog.getOpenFileName(self, "Select a video or XML", path_home, "Video files (*.fcpxml *.m4v *.m2v *.mpg *.mp4 *.mov)")[0]#.toUtf8() + if not filepath == '': + chapters_list, chapters_dict = get_video_chapters(self, filepath) + + self.dict_of_videos[self.selected_video][1] = self.dict_of_videos[self.selected_video][1] + chapters_list + for chapter in chapters_dict.keys(): + self.dict_of_videos[self.selected_video][2][chapter] = chapters_dict[chapter] + + populate_chapters_list(self) + +def get_video_chapters(self, filepath): + chapters_list = [] + chapters_dict = {} + if filepath.split('.')[-1] == 'fcpxml': + chapters_xml = codecs.open(filepath, 'r', 'utf-8').read() + for chapter_line in chapters_xml.split('' in chapter_line and ('start="' in chapter_line.split('/>')[0] and 'duration="' in chapter_line.split('/>')[0]): + mark = convert_to_timecode(chapter_line.split('start="')[1].split('"')[0], chapter_line.split('duration="')[1].split('"')[0]) + name = check_name(self, chapters_list, chapter_line.split('value="')[1].split('"')[0]) + chapters_list.append(name) + chapters_dict[name] = mark + else: + chapters_xml = unicode(subprocess.Popen([ffprobe_bin, '-loglevel', 'error', '-show_chapters', '-print_format', 'xml', filepath], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.read(), 'utf-8') + for chapter_line in chapters_xml.split('' in chapter_line: + mark = convert_to_timecode(chapter_line.split('start="')[1].split('"')[0], chapter_line.split('time_base="')[1].split('"')[0]) + name = check_name(self, chapters_list, chapter_line.split('value="')[1].split('"')[0]) + chapters_list.append(name) + chapters_dict[name] = mark + + return chapters_list, chapters_dict + +def chapter_selected(self): + self.selected_video_chapter = self.options_panel_video_chapters_list.currentItem().text().split('\n')[0] + self.options_panel_video_chapters_remove.setEnabled(True) + self.options_panel_video_chapters_edit.setEnabled(True) + chapter_seek_in_timeline(self) + +def chapter_seek_in_timeline(self): + self.preview_video_obj.seek(convert_timecode_to_miliseconds(self.dict_of_videos[self.selected_video][2][self.selected_video_chapter])) + +def add_chapter(self): + self.selected_video_chapter = None + self.options_panel_video_chapters_timecode.setText('') + self.options_panel_video_chapters_name.setText('') + show_edit_chapter(self) + +def append_chapter(self, name, timecode): + if self.selected_video_chapter: + self.dict_of_videos[self.selected_video][1].remove(self.selected_video_chapter) + del self.dict_of_videos[self.selected_video][2][self.selected_video_chapter] + self.dict_of_videos[self.selected_video][1].append(name) + self.dict_of_videos[self.selected_video][2][name] = timecode + +def confirm_edit_chapter(self): + append_chapter(self, self.options_panel_video_chapters_name.text(), self.options_panel_video_chapters_timecode.text()) + hide_edit_chapter(self) + update_changes(self) + +def check_chapter_name(self): + None + +def hide_edit_chapter(self): + self.options_panel_video_chapters_list.setGeometry(10,70,self.options_panel_video_panel.width()-20,self.options_panel_video_panel.height()-115) + self.options_panel_video_chapters_list.setEnabled(True) + self.options_panel_video_chapters_name_label.setShown(False) + self.options_panel_video_chapters_name.setShown(False) + self.options_panel_video_chapters_timecode_label.setShown(False) + self.options_panel_video_chapters_timecode.setShown(False) + self.options_panel_video_chapters_edit_confirm.setShown(False) + self.options_panel_video_chapters_edit_cancel.setShown(False) + self.options_panel_video_chapters_add.setShown(True) + self.options_panel_video_chapters_remove.setShown(True) + self.options_panel_video_chapters_edit.setShown(True) + self.options_panel_video_chapters_import.setShown(True) + +def remove_chapter(self): + del self.dict_of_videos[self.selected_video][2][self.selected_video_chapter] + self.dict_of_videos[self.selected_video][1].remove(self.selected_video_chapter) + self.selected_video_chapter = None + update_changes(self) + +def edit_chapter(self): + self.options_panel_video_chapters_name.setText(self.selected_video_chapter) + self.options_panel_video_chapters_timecode.setText(self.dict_of_videos[self.selected_video][2][self.selected_video_chapter]) + check_chapter_name(self) + show_edit_chapter(self) + +def show_edit_chapter(self): + self.options_panel_video_chapters_list.setGeometry(10,70,self.options_panel_video_panel.width()-20,self.options_panel_video_panel.height()-135) + self.options_panel_video_chapters_list.setEnabled(False) + self.options_panel_video_chapters_name_label.setShown(True) + self.options_panel_video_chapters_name.setShown(True) + self.options_panel_video_chapters_timecode_label.setShown(True) + self.options_panel_video_chapters_timecode.setShown(True) + self.options_panel_video_chapters_edit_confirm.setShown(True) + self.options_panel_video_chapters_edit_cancel.setShown(True) + self.options_panel_video_chapters_add.setShown(False) + self.options_panel_video_chapters_remove.setShown(False) + self.options_panel_video_chapters_edit.setShown(False) + self.options_panel_video_chapters_import.setShown(False) + +def populate_chapters_list(self): + self.options_panel_video_chapters_list.clear() + list_of_chapters_in_order = sort_list_of_chapters(self.dict_of_videos[self.selected_video][2]) + + self.dict_of_videos[self.selected_video][1] = list_of_chapters_in_order + + for chapter in self.dict_of_videos[self.selected_video][1]: + icon = QtGui.QIcon(os.path.join(path_graphics, 'chapter.png')) + self.options_panel_video_chapters_list.addItem(QtGui.QListWidgetItem(icon, unicode(str(chapter), 'utf-8') + '\n' + self.dict_of_videos[self.selected_video][2][chapter])) + +################################################################################################### +###################################################################################### GENERATE DVD +################################################################################################### + +def dvd_generate(self): + self.preview_video_widget.setShown(False) + if not self.actual_project_file: + self.generate_dvd_thread_thread.actual_project_file = os.path.join(path_home, self.project_name + '.odvdp') + else: + self.generate_dvd_thread_thread.actual_project_file = self.actual_project_file + self.generate_dvd_thread_thread.project_name = self.project_name + + if self.audio_formats[self.selected_audio_format] == 'MP2 48kHz': + self.generate_dvd_thread_thread.audio_codec = 'pcm_s16le' + + if self.video_formats[self.selected_video_format].split(' ')[0] == 'NTSC': + self.generate_dvd_thread_thread.framerate = '29.97' + + self.generate_dvd_thread_thread.height = int(self.video_formats[self.selected_video_format].split(' ')[1].split('x')[1]) + self.generate_dvd_thread_thread.video_format = self.video_formats[self.selected_video_format].split(' ')[0].lower() + self.generate_dvd_thread_thread.video_resolutions = self.resolutions#self.video_formats[self.selected_video_format].split(' ')[1].lower() + + self.generate_dvd_thread_thread.aspect_ratio = self.aspect_ratios[self.selected_aspect_ratio] + + self.generate_dvd_thread_thread.selected_menu_encoding = self.selected_menu_encoding + self.generate_dvd_thread_thread.selected_video_encoding = self.selected_video_encoding + + self.generate_dvd_thread_thread.selected_menu_twopass = self.selected_menu_twopass + self.generate_dvd_thread_thread.selected_video_twopass = self.selected_video_twopass + + self.generate_dvd_thread_thread.selected_gop_size = self.selected_gop_size + self.generate_dvd_thread_thread.selected_menu_bitrate = self.selected_menu_bitrate + self.generate_dvd_thread_thread.selected_menu_max_bitrate = self.selected_menu_max_bitrate + self.generate_dvd_thread_thread.selected_video_bitrate = self.selected_video_bitrate + self.generate_dvd_thread_thread.selected_video_max_bitrate = self.selected_video_max_bitrate + + self.generate_dvd_thread_thread.list_of_menus = self.list_of_menus + self.generate_dvd_thread_thread.list_of_videos = self.list_of_videos + self.generate_dvd_thread_thread.dict_of_menus = self.dict_of_menus + self.generate_dvd_thread_thread.dict_of_videos = self.dict_of_videos + + self.generate_dvd_thread_thread.has_menus = self.has_menus + + self.generate_dvd_thread_thread.audio_datarate = int(self.selected_audio_datarate.split(' ')[0]) + + self.generate_dvd_thread_thread.generate_ddp = self.finalize_panel_generate_button_ddp_checkbox.isChecked() + self.generate_dvd_thread_thread.generate_iso = self.finalize_panel_generate_button_iso_checkbox.isChecked() + + self.generate_dvd_thread_thread.start() + +def generate_effect(self, widget, effect_type, duration, startValue, endValue): + widget.setDuration(duration) + if effect_type == 'geometry': + widget.setStartValue(QtCore.QRect(startValue[0],startValue[1],startValue[2],startValue[3])) + widget.setEndValue(QtCore.QRect(endValue[0],endValue[1],endValue[2],endValue[3])) + elif effect_type == 'opacity': + widget.setStartValue(startValue) + widget.setEndValue(endValue) + widget.start() + +app = QtGui.QApplication(sys.argv) +app.addLibraryPath(app.applicationDirPath() + "/../PlugIns") +#app.setStyle("clearlooks") +app.setStyle("plastique") +app.setApplicationName("Open DVD Producer") +font_database = QtGui.QFontDatabase() +font_database.addApplicationFont(os.path.join(path_opendvdproducer, 'Ubuntu-RI.ttf')) +font_database.addApplicationFont(os.path.join(path_opendvdproducer, 'Ubuntu-R.ttf')) +font_database.addApplicationFont(os.path.join(path_opendvdproducer, 'Ubuntu-B.ttf')) +font_database.addApplicationFont(os.path.join(path_opendvdproducer, 'Ubuntu-BI.ttf')) +font_database.addApplicationFont(os.path.join(path_opendvdproducer, 'UbuntuMono-R.ttf')) +app.setFont(QtGui.QFont('Ubuntu', interface_font_size)) +app.setDesktopSettingsAware(False) +app.main = main_window() + +app.main.show() + +sys.exit(app.exec_())