def create_audio_sync_compound_clip(): selection = gui.media_list_view.get_selected_media_objects() if len(selection) != 2: return video_file = selection[0].media_file audio_file = selection[1].media_file # Can't sync coumpound clips if utils.is_mlt_xml_file(video_file.path) == True or utils.is_mlt_xml_file( audio_file.path) == True: dialogutils.warning_message( _("Cannot Create Audio Sync Clip from MLT XML Container Clips!"), _("Audio syncing MLT XML Container Clips is not supported."), gui.editor_window.window, True) return # Can't sync 2 audio clips if video_file.type == appconsts.AUDIO and audio_file.type == appconsts.AUDIO: dialogutils.warning_message( _("Cannot Create Audio Sync Container Clip from 2 Audio Clips!"), _("One of the media items needs to be a video clip."), gui.editor_window.window, True) return if video_file.type == appconsts.VIDEO and audio_file.type == appconsts.AUDIO: pass elif video_file.type == appconsts.AUDIO and audio_file.type == appconsts.VIDEO: video_file, audio_file = audio_file, video_file else: print( "2 video files, video audio assignments determined by selection order" ) global _compare_dialog_thread _compare_dialog_thread = AudioCompareActiveThread() _compare_dialog_thread.start() # This or GUI freezes, we really can't do Popen.wait() in a Gtk thread clapperless_thread = ClapperlesLaunchThread(video_file.path, audio_file.path, _compound_offsets_complete) clapperless_thread.start()
def create_audio_sync_compound_clip(): selection = gui.media_list_view.get_selected_media_objects() if len(selection) != 2: return video_file = selection[0].media_file audio_file = selection[1].media_file # Can't sync coumpound clips if utils.is_mlt_xml_file(video_file.path) == True or utils.is_mlt_xml_file(audio_file.path) == True: # This isn't translated because 1.14 translation window is close, translation coming for 1.16 dialogutils.warning_message(_("Cannot Create Audio Sync Compound Clip from Compound Clips!"), _("Audio syncing Compound Clips is not supported."), gui.editor_window.window, True) return # Can't sync 2 audio clips if video_file.type == appconsts.AUDIO and audio_file.type == appconsts.AUDIO: # This isn't translated because 1.14 translation window is close, translation coming for 1.16 dialogutils.warning_message(_("Cannot Create Audio Sync Compound Clip from 2 Audio Clips!"), _("One of the media items needs to be a video clip."), gui.editor_window.window, True) return if video_file.type == appconsts.VIDEO and audio_file.type == appconsts.AUDIO: pass elif video_file.type == appconsts.AUDIO and audio_file.type == appconsts.VIDEO: video_file, audio_file = audio_file, video_file else: print "2 video files, video audio assignments determined by selection order" global _compare_dialog_thread _compare_dialog_thread = AudioCompareActiveThread() _compare_dialog_thread.start() # This or GUI freezes, we really can't do Popen.wait() in a Gtk thread clapperless_thread = ClapperlesLaunchThread(video_file.path, audio_file.path, _compound_offsets_complete) clapperless_thread.start()
def select_sync_clip_mouse_pressed(event, frame): sync_clip = _get_sync_tline_clip(event, frame) if sync_clip == None: return # selection wasn't good if utils.is_mlt_xml_file(sync_clip.path) == True: # This isn't translated because 1.14 translation window is close, translation coming for 1.16 dialogutils.warning_message( _("Cannot Timeline Audio Sync with MLT XML Container Clips!"), _("Audio syncing for MLT XML Container Clips is not supported."), gui.editor_window.window, True) return sync_track = tlinewidgets.get_track(event.y) sync_clip_index = sync_track.clips.index(sync_clip) _tline_sync_data.sync_clip = sync_clip _tline_sync_data.sync_track = sync_track _tline_sync_data.sync_clip_index = sync_clip_index # TImeline media offset for clips sync_clip_start_in_tline = sync_track.clip_start(sync_clip_index) _tline_sync_data.origin_clip_start_in_tline = _tline_sync_data.origin_track.clip_start( _tline_sync_data.origin_clip_index) _tline_sync_data.clip_tline_media_offset = ( sync_clip_start_in_tline - sync_clip.clip_in) - (_tline_sync_data.origin_clip_start_in_tline - _tline_sync_data.origin_clip.clip_in) gdk_window = gui.tline_display.get_parent_window() gdk_window.set_cursor(Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR)) global _compare_dialog_thread _compare_dialog_thread = AudioCompareActiveThread() _compare_dialog_thread.start() # This or GUI freezes, we really can't do Popen.wait() in a Gtk thread clapperless_thread = ClapperlesLaunchThread( _tline_sync_data.origin_clip.path, sync_clip.path, _tline_sync_offsets_computed_callback) clapperless_thread.start() # Edit consumes selection movemodes.clear_selected_clips() updater.repaint_tline()
def select_sync_clip_mouse_pressed(event, frame): sync_clip = _get_sync_tline_clip(event, frame) if sync_clip == None: return # selection wasn't good if utils.is_mlt_xml_file(sync_clip.path) == True: # This isn't translated because 1.14 translation window is close, translation coming for 1.16 dialogutils.warning_message(_("Cannot Timeline Audio Sync with Compound Clips!"), _("Audio syncing for Compound Clips is not supported."), gui.editor_window.window, True) return sync_track = tlinewidgets.get_track(event.y) sync_clip_index = sync_track.clips.index(sync_clip) _tline_sync_data.sync_clip = sync_clip _tline_sync_data.sync_track = sync_track _tline_sync_data.sync_clip_index = sync_clip_index # TImeline media offset for clips sync_clip_start_in_tline = sync_track.clip_start(sync_clip_index) _tline_sync_data.origin_clip_start_in_tline = _tline_sync_data.origin_track.clip_start(_tline_sync_data.origin_clip_index) _tline_sync_data.clip_tline_media_offset = (sync_clip_start_in_tline - sync_clip.clip_in) - (_tline_sync_data.origin_clip_start_in_tline - _tline_sync_data.origin_clip.clip_in) gdk_window = gui.tline_display.get_parent_window(); gdk_window.set_cursor(Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR)) global _compare_dialog_thread _compare_dialog_thread = AudioCompareActiveThread() _compare_dialog_thread.start() # This or GUI freezes, we really can't do Popen.wait() in a Gtk thread clapperless_thread = ClapperlesLaunchThread(_tline_sync_data.origin_clip.path, sync_clip.path, _tline_sync_offsets_computed_callback) clapperless_thread.start() # Edit consumes selection movemodes.clear_selected_clips() updater.repaint_tline()
def get_p_clip(clip): """ Creates pickleable version of MLT Producer object """ s_clip = copy.copy(clip) # Because of MLT misfeature of changing project profile when loading MLT XML files we need to create new modified XML files when # saving to change profile. # Underlying reason: https://github.com/mltframework/mlt/issues/212 if _xml_new_paths_for_profile_change != None and hasattr( s_clip, "path") and s_clip.path != None and utils.is_mlt_xml_file( s_clip.path) == True: try: new_path = _xml_new_paths_for_profile_change[s_clip.path] print "XML path replace for clip:", s_clip.path, new_path s_clip.path = new_path except: # Something is really wrong, this should not be possible print "Failed to find a new XML file for path:", s_clip.path # Set 'type' attribute for MLT object type # This IS NOT USED anywhere anymore and should be removed. s_clip.type = 'Mlt__Producer' # Get replace filters filters = [] try: # This fails for blank clips # We'll just save them with empty filters array for i in range(0, len(clip.filters)): f = clip.filters[i] filters.append(get_p_filter(f)) except: pass s_clip.filters = filters # Replace mute filter object with boolean to flag mute if s_clip.mute_filter != None: s_clip.mute_filter = True # Get replace sync data if s_clip.sync_data != None: s_clip.sync_data = get_p_sync_data(s_clip.sync_data) if _fps_conv_mult != 1.0: _update_clip_in_out_for_fps_change(s_clip) # Remove unpicleable attributes remove_attrs(s_clip, CLIP_REMOVE) # Don't save waveform data. s_clip.waveform_data = None # Add pickleable filters s_clip.filters = filters # Do proxy mode convert if needed if (project_proxy_mode == appconsts.CONVERTING_TO_USE_PROXY_MEDIA or project_proxy_mode == appconsts.CONVERTING_TO_USE_ORIGINAL_MEDIA): try: # This fails when it is supposed to fail: for clips that have no proxy and pattern producers and blanks s_clip.path = proxy_path_dict[s_clip.path] except: pass # Change paths when doing snapshot save try: # This fails for pattern producers and blanks if snapshot_paths != None: s_clip.path = snapshot_paths[s_clip.path] except: pass return s_clip
def save_project(project, file_path, changed_profile_desc=None): """ Creates pickleable project object """ print "Save project " + os.path.basename(file_path) # Get shallow copy s_proj = copy.copy(project) # Implements "change profile" functionality global _fps_conv_mult, _xml_new_paths_for_profile_change _fps_conv_mult = 1.0 if changed_profile_desc != None: _fps_conv_mult = mltprofiles.get_profile(changed_profile_desc).fps( ) / mltprofiles.get_profile(s_proj.profile_desc).fps() s_proj.profile_desc = changed_profile_desc _xml_new_paths_for_profile_change = { } # dict acts also as a flag to show that profile change save is happening new_profile = mltprofiles.get_profile(changed_profile_desc) print "Saving changed profile project: ", changed_profile_desc print "FPS conversion multiplier:", _fps_conv_mult else: _xml_new_paths_for_profile_change = None # None value acts also as a flag to show that profile change save is _not_ happening # Set current sequence index s_proj.c_seq_index = project.sequences.index(project.c_seq) # Set project SAVEFILE_VERSION to current in case this is a resave of older file type. # Older file type has been converted to newer file type on load. s_proj.SAVEFILE_VERSION = appconsts.SAVEFILE_VERSION # Init proxy convert data global project_proxy_mode, proxy_path_dict project_proxy_mode = s_proj.proxy_data.proxy_mode proxy_path_dict = {} # Replace media file objects with pickleable copys media_files = {} for k, v in s_proj.media_files.iteritems(): s_media_file = copy.copy(v) # Because of MLT misfeature of changing project profile when loading MLT XML files we need to create new modified XML files when # saving to change profile. # Underlying reason: https://github.com/mltframework/mlt/issues/212 if changed_profile_desc != None and s_media_file.path != None and utils.is_mlt_xml_file( s_media_file.path) == True: new_xml_file_path = _save_changed_xml_file(s_media_file, new_profile) _xml_new_paths_for_profile_change[ s_media_file.path] = new_xml_file_path s_media_file.path = new_xml_file_path print "XML path replace for media:", s_media_file.path, new_xml_file_path # Remove unpicleable attrs remove_attrs(s_media_file, MEDIA_FILE_REMOVE) # Convert media files between original and proxy files if project_proxy_mode == appconsts.CONVERTING_TO_USE_PROXY_MEDIA: if s_media_file.has_proxy_file: proxy_path_dict[ s_media_file.path] = s_media_file.second_file_path s_media_file.set_as_proxy_media_file() elif project_proxy_mode == appconsts.CONVERTING_TO_USE_ORIGINAL_MEDIA: if s_media_file.is_proxy_file: proxy_path_dict[ s_media_file.path] = s_media_file.second_file_path s_media_file.set_as_original_media_file() # Change paths when doing snapshot save. Image sequences are not # md5 hashed and are saved in folders and need to be looked up by relative search # when loading. if snapshot_paths != None: if s_media_file.type != appconsts.PATTERN_PRODUCER and s_media_file.type != appconsts.IMAGE_SEQUENCE: s_media_file.path = snapshot_paths[s_media_file.path] media_files[s_media_file.id] = s_media_file s_proj.media_files = media_files # Replace sequences with pickleable objects sequences = [] for i in range(0, len(project.sequences)): add_seq = project.sequences[i] sequences.append(get_p_sequence(add_seq)) s_proj.sequences = sequences # Remove unpickleable attributes remove_attrs(s_proj, PROJECT_REMOVE) # Write out file. write_file = file(file_path, "wb") pickle.dump(s_proj, write_file)
def get_p_clip(clip): """ Creates pickleable version of MLT Producer object """ s_clip = copy.copy(clip) # Because of MLT misfeature of changing project profile when loading MLT XML files we need to create new modified XML files when # saving to change profile. # Underlying reason: https://github.com/mltframework/mlt/issues/212 if _xml_new_paths_for_profile_change != None and hasattr(s_clip, "path") and s_clip.path != None and utils.is_mlt_xml_file(s_clip.path) == True: try: new_path = _xml_new_paths_for_profile_change[s_clip.path] #print "XML path replace for clip:", s_clip.path, new_path s_clip.path = new_path except: # Something is really wrong, this should not be possible # print "Failed to find a new XML file for path:", s_clip.path pass # Set 'type' attribute for MLT object type # This IS NOT USED anywhere anymore and should be removed. s_clip.type = 'Mlt__Producer' # Get replace filters filters = [] try: # This fails for blank clips # We'll just save them with empty filters array for i in range(0, len(clip.filters)): f = clip.filters[i] filters.append(get_p_filter(f)) except: pass s_clip.filters = filters # Replace mute filter object with boolean to flag mute if s_clip.mute_filter != None: s_clip.mute_filter = True # Get replace sync data if s_clip.sync_data != None: s_clip.sync_data = get_p_sync_data(s_clip.sync_data) if _fps_conv_mult != 1.0: _update_clip_in_out_for_fps_change(s_clip) # Remove unpicleable attributes remove_attrs(s_clip, CLIP_REMOVE) # Don't save waveform data. s_clip.waveform_data = None # Add pickleable filters s_clip.filters = filters # Do proxy mode convert if needed if (project_proxy_mode == appconsts.CONVERTING_TO_USE_PROXY_MEDIA or project_proxy_mode == appconsts.CONVERTING_TO_USE_ORIGINAL_MEDIA): try: # This fails when it is supposed to fail: for clips that have no proxy and pattern producers and blanks s_clip.path = proxy_path_dict[s_clip.path] except: pass # Change paths when doing snapshot save try: # This fails for pattern producers and blanks if snapshot_paths != None: s_clip.path = snapshot_paths[s_clip.path] except: pass return s_clip
def save_project(project, file_path, changed_profile_desc=None): """ Creates pickleable project object """ print "Saving project..." # + os.path.basename(file_path) # Get shallow copy s_proj = copy.copy(project) # Implements "change profile" functionality global _fps_conv_mult, _xml_new_paths_for_profile_change _fps_conv_mult = 1.0 if changed_profile_desc != None: _fps_conv_mult = mltprofiles.get_profile(changed_profile_desc).fps() / mltprofiles.get_profile(s_proj.profile_desc).fps() s_proj.profile_desc = changed_profile_desc _xml_new_paths_for_profile_change = {} # dict acts also as a flag to show that profile change save is happening new_profile = mltprofiles.get_profile(changed_profile_desc) #print "Saving changed profile project: ", changed_profile_desc #print "FPS conversion multiplier:", _fps_conv_mult else: _xml_new_paths_for_profile_change = None # None value acts also as a flag to show that profile change save is _not_ happening # Set current sequence index s_proj.c_seq_index = project.sequences.index(project.c_seq) # Set project SAVEFILE_VERSION to current in case this is a resave of older file type. # Older file type has been converted to newer file type on load. s_proj.SAVEFILE_VERSION = appconsts.SAVEFILE_VERSION # Init proxy convert data global project_proxy_mode, proxy_path_dict project_proxy_mode = s_proj.proxy_data.proxy_mode proxy_path_dict = {} # Replace media file objects with pickleable copys media_files = {} for k, v in s_proj.media_files.iteritems(): s_media_file = copy.copy(v) # Because of MLT misfeature of changing project profile when loading MLT XML files we need to create new modified XML files when # saving to change profile. # Underlying reason: https://github.com/mltframework/mlt/issues/212 if changed_profile_desc != None and s_media_file.path != None and utils.is_mlt_xml_file(s_media_file.path) == True: new_xml_file_path = _save_changed_xml_file(s_media_file, new_profile) _xml_new_paths_for_profile_change[s_media_file.path] = new_xml_file_path s_media_file.path = new_xml_file_path #print "XML path replace for media:", s_media_file.path, new_xml_file_path # Remove unpicleable attrs remove_attrs(s_media_file, MEDIA_FILE_REMOVE) # Convert media files between original and proxy files if project_proxy_mode == appconsts.CONVERTING_TO_USE_PROXY_MEDIA: if s_media_file.has_proxy_file: proxy_path_dict[s_media_file.path] = s_media_file.second_file_path s_media_file.set_as_proxy_media_file() elif project_proxy_mode == appconsts.CONVERTING_TO_USE_ORIGINAL_MEDIA: if s_media_file.is_proxy_file: proxy_path_dict[s_media_file.path] = s_media_file.second_file_path s_media_file.set_as_original_media_file() # Change paths when doing snapshot save. Image sequences are not # md5 hashed and are saved in folders and need to be looked up by relative search # when loading. if snapshot_paths != None: if s_media_file.type != appconsts.PATTERN_PRODUCER and s_media_file.type != appconsts.IMAGE_SEQUENCE: s_media_file.path = snapshot_paths[s_media_file.path] media_files[s_media_file.id] = s_media_file s_proj.media_files = media_files # Replace sequences with pickleable objects sequences = [] for i in range(0, len(project.sequences)): add_seq = project.sequences[i] sequences.append(get_p_sequence(add_seq)) s_proj.sequences = sequences # Remove unpickleable attributes remove_attrs(s_proj, PROJECT_REMOVE) # Write out file. with atomicfile.AtomicFileWriter(file_path, "wb") as afw: write_file = afw.get_file() pickle.dump(s_proj, write_file)