diff --git a/openpype/hosts/flame/api/render_utils.py b/openpype/hosts/flame/api/render_utils.py index 1b086646cc..bc9ebb83d4 100644 --- a/openpype/hosts/flame/api/render_utils.py +++ b/openpype/hosts/flame/api/render_utils.py @@ -1,4 +1,10 @@ import os +import sys +import traceback +from xml.etree import ElementTree as ET +import shutil +import openpype.lib +import six def export_clip(export_path, clip, preset_path, **kwargs): @@ -123,3 +129,317 @@ def get_preset_path_by_xml_name(xml_preset_name): # if nothing found then return False return False + + +def get_open_clip( + openclip_file_path, feed_data, recursive=False): + + # establish media script path and test it + media_script_path = "/opt/Autodesk/mio/current/dl_get_media_info" + if not os.path.isfile(media_script_path): + raise IOError("Media Scirpt does not exist: `{}`".format( + media_script_path)) + + # new feed variables: + feed_path = feed_data["path"] + feed_basename = os.path.basename(feed_path) + feed_version_name = feed_data["version"] + + clip_uploaded = False + create_new_clip = False + + ext_whitelist = [ + "cin", "als", "jpg", "jpeg", "pict", "pct", "picio", + "sgi", "pic", "tga", "iff", "tdi", "tif", "tiff", "rla", + "cin.pxz", "tif.pxz", "tiff.pxz", "dpx", "dpx.pxz", + "hdr", "png", "exr", "exr.pxz", "psd" + ] + + feed_ext = os.path.splitext(feed_basename)[1][1:].lower() + + if feed_ext not in ext_whitelist: + print("File extension `{}` is not supported".format(feed_ext)) + return False + + if not os.path.isfile(openclip_file_path): + # openclip does not exist yet and will be created + feed_path = os.path.abspath(feed_path) + tmp_file = openclip_file_path + create_new_clip = True + clip_uploaded = True + else: + # openclip will be updated via temp.clip file + tmp_name = "tmp.clip" + feed_path = os.path.abspath(feed_path) + feed_dir = os.path.dirname(feed_path) + + # output a temp file + tmp_file = os.path.join(feed_dir, tmp_name) + if os.path.isfile(tmp_file): + os.remove(tmp_file) + + print("Temp File: {}".format(tmp_file)) + + # Write output of getMediaScript to file + cmd_args = [media_script_path, feed_path] + if recursive: + print("recursive enabled on dl_get_media_info") + cmd_args = [media_script_path, "-r", feed_path] + + # execute creation of clip xml template data + try: + output = openpype.lib.run_subprocess(cmd_args) + except TypeError: + print("Error createing tmp_file") + six.reraise(*sys.exc_info()) + + with open(tmp_file, "w") as f: + f.write("{}".format(output)) + + # Check media type for valid extension + try: + tmp_xml = ET.parse(tmp_file) + except: + print("XML is probably empty.") + print('{}'.format(traceback.print_exc())) + if os.path.isfile(tmp_file): + os.remove(tmp_file) + return False + + for newTrack in tmp_xml.iter('track'): + new_path_obj = newTrack.find("feeds/feed/spans/span/path") + new_path = new_path_obj.text + print("tmp_xml new_path: {}".format(new_path)) + + new_path_ext = os.path.splitext(new_path)[1][1:].strip().lower() + if new_path_ext in ext_whitelist: + print("Found media `{}`".format(new_path_ext)) + else: + print("Extension {} is not supported".format( + new_path_ext)) + if os.path.isfile(tmp_file): + os.remove(tmp_file) + return False + + if not create_new_clip: + print("Updating openClip ..") + + try: + source_xml = ET.parse(openclip_file_path) + except: + print("XML is probably empty.") + print('%s' % traceback.print_exc()) + if os.path.isfile(tmp_file): + os.remove(tmp_file) + return False + + try: + new_xml = ET.parse(tmp_file) + except: + print("XML is probably empty.") + print('%s' % traceback.print_exc()) + if os.path.isfile(tmp_file): + os.remove(tmp_file) + return False + + try: + feed_exists = False + feed_added = 0 + + src_editRateNumerator = None + src_editRateDenominator = None + src_nbTicks = None + src_rate = None + src_dropMode = None + + for srcTrack in source_xml.iter('track'): + src_editRateNumeratorObj = srcTrack.find('editRate/numerator') + src_editRateNumerator = src_editRateNumeratorObj.text + src_editRateDenominatorObj = srcTrack.find( + 'editRate/denominator') + src_editRateDenominator = src_editRateDenominatorObj.text + + for srcFeed in srcTrack.iter('feed'): + src_nbTicksObj = srcFeed.find('startTimecode/nbTicks') + src_nbTicks = src_nbTicksObj.text + src_rateObj = srcFeed.find('startTimecode/rate') + src_rate = src_rateObj.text + src_dropModeObj = srcFeed.find('startTimecode/dropMode') + src_dropMode = src_dropModeObj.text + break + else: + continue + break + + print("Source editRate/numerator: %s" % src_editRateNumerator) + print("Source editRate/denominator: %s" % src_editRateDenominator) + print("Source startTimecode/nbTicks: %s" % src_nbTicks) + print("Source startTimecode/rate: %s" % src_rate) + print("Source startTimecode/dropMode: %s" % src_dropMode) + + # Get new feed from file + for newTrack in new_xml.iter('track'): + uid = newTrack.get('uid') + newFeed = newTrack.find('feeds/feed') + + feedHandler = newFeed.find("./handler") + newFeed.remove(feedHandler) + + if src_editRateNumerator: + new_editRateNumeratorObject = newTrack.find( + "feeds/feed/sampleRate/numerator") + new_editRateNumeratorObject.text = src_editRateNumerator + if src_editRateDenominator: + new_editRateDenominatorObject = newTrack.find( + "feeds/feed/sampleRate/denominator") + new_editRateDenominatorObject.text = src_editRateDenominator + if src_rate: + new_rateObject = newTrack.find( + "feeds/feed/startTimecode/rate") + new_rateObject.text = src_rate + if src_nbTicks: + new_nbTicksObject = newTrack.find( + "feeds/feed/startTimecode/nbTicks") + new_nbTicksObject.text = src_nbTicks + if src_dropMode: + new_dropModeObj = newTrack.find( + "feeds/feed/startTimecode/dropMode") + new_dropModeObj.text = src_dropMode + + new_path_obj = newTrack.find("feeds/feed/spans/span/path") + new_path = new_path_obj.text + + print(">> uid: {}".format(uid)) + print(">> new_path: {}".format(new_path)) + + # Check for path in sourceFile + # If Path exists ... skip append + for srcPath in source_xml.iter('path'): + if new_path == srcPath.text: + print("Element exists in clip... skipping append") + feed_exists = True + + if not feed_exists: + # Append new feed to source track + for srcTrack in source_xml.iter('track'): + newFeed.set('vuid', feed_version_name) + srcTrack.find('feeds').append(newFeed) + print( + "Appending new feed: {}".format(feed_version_name)) + feed_added += 1 + + if feed_added > 0: + # Append vUID to versions + newVersion = source_xml.find('versions') + newVersionElement = ET.Element( + "version", {"type": "version", "uid": feed_version_name}) + newVersion.insert(0, newVersionElement) + xmlRoot = source_xml.getroot() + + # Clean tmp_file - brute force remove errant + print("Removing Handler") + for handler in xmlRoot.findall("./handler"): + print("Handler found") + xmlRoot.remove(handler) + + resultXML = ET.tostring(xmlRoot).decode('utf-8') + + # fist create backup + create_openclip_backup_file(openclip_file_path) + + out_file = openclip_file_path + + print("Adding feed version: {}".format(feed_version_name)) + + with open(out_file, "w") as f: + f.write(resultXML) + + print("openClip Updated: {}".format(out_file)) + + clip_uploaded = True + + if os.path.isfile(tmp_file): + os.remove(tmp_file) + + except: + print("Failed reading XML") + print('%s' % traceback.print_exc()) + if os.path.isfile(tmp_file): + os.remove(tmp_file) + return False + + else: + # New openClip + print("Building new openClip") + + # Update uid name with element_name + try: + new_xml = ET.parse(tmp_file) + except: + print("Failed reading XML") + print('%s' % traceback.print_exc()) + if os.path.isfile(tmp_file): + os.remove(tmp_file) + return False + + try: + for newFeed in new_xml.iter('feeds'): + feed = newFeed.find('feed') + feed.set('vuid', feed_basename) + + feedHandler = feed.find("./handler") + feed.remove(feedHandler) + + for newVersion in new_xml.iter('versions'): + newVersion.set('currentVersion', feed_basename) + version = newVersion.find('version') + version.set('uid', feed_basename) + version.set('type', 'version') + + xmlRoot = new_xml.getroot() + + # Clean tmp_file - brute force remove errant + print("Removing Handler") + for handler in xmlRoot.findall("./handler"): + print("Handler found") + xmlRoot.remove(handler) + + resultXML = ET.tostring(xmlRoot).decode('utf-8') + + print("Adding feed version: %s" % feed_basename) + + with open(tmp_file, "w") as f: + f.write(resultXML) + + print("openClip Updated: %s" % tmp_file) + + clip_uploaded = True + + except: + print("Failed to update openClip: %s" % tmp_file) + print('%s' % traceback.print_exc()) + + return clip_uploaded + + +def create_openclip_backup_file(file): + bck_file = "{}.bak".format(file) + # if backup does not exist + if not os.path.isfile(bck_file): + shutil.copy2(file, bck_file) + else: + # in case it exists and is already multiplied + created = False + for _i in range(1, 99): + bck_file = "{name}.bak.{idx:0>2}".format( + name=file, + idx=_i) + # create numbered backup file + if not os.path.isfile(bck_file): + shutil.copy2(file, bck_file) + created = True + break + # in case numbered does not exists + if not created: + bck_file = "{}.bak.last".format(file) + shutil.copy2(file, bck_file)