Example #1
0
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()
Example #2
0
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()
Example #3
0
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()
Example #4
0
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()
Example #5
0
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
Example #6
0
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)
Example #7
0
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
Example #8
0
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)