def col_txt_endhandle_change(self, cell, path, new_text): model = ListStore.projShotStore shot_name = model[path][const.COLUMN_SHOTLIST] model[path][const.COLUMN_END_HANDLE] = int(new_text) db_shot_record = self.store.getShotFromName(shot_name).first() util.changesetRecord(db_shot_record, 'endhandle', new_text) self.store.shotSave(db_shot_record) return True
def col_txt_stereo_change(self, cell, path, new_text): model = ListStore.projShotStore shot_name = model[path][const.COLUMN_SHOTLIST] model[path][const.COLUMN_STEREO] = new_text db_shot_record = self.store.getShotFromName(shot_name).first() util.changesetRecord(db_shot_record, 'isstereo', new_text) self.store.shotSave(db_shot_record) return True
def col_txt_seqnum_change(self, cell, path, new_text): model = ListStore.projShotStore shot_name = model[path][const.COLUMN_SHOTLIST] model[path][const.COLUMN_NEW_SEQ_NUM] = new_text db_shot_record = self.store.getShotFromName(shot_name).first() util.changesetRecord(db_shot_record, 'shotnumber', new_text) self.store.shotSave(db_shot_record) return True
def writePublishInfo(self, mov_path, thumb_path, resolution_dir, frame_info, shot_info): util.changesetRecord(shot_info, "movpath", mov_path) util.changesetRecord(shot_info, "jpgpath", thumb_path) util.changesetRecord(shot_info, "publishpath", resolution_dir) util.changesetRecord(shot_info, "newstartframe", frame_info["START"]) util.changesetRecord(shot_info, "newendframe", frame_info["END"]) util.changesetRecord(shot_info, "publishdate", datetime.now()) util.changesetRecord(shot_info, "ispublish", 'Y')
def clkPublish(self, widget, event, data=None): tmp_path = path_join(const.SCAN_ROOT, "tmp") # tmp_path exists if not exists(tmp_path): makedirs(tmp_path) # 물론 projectShot에서 체크된 된것만 수행한다) for row in ListStore.projShotStore: if not row[const.COLUMN_CHOICE]: continue # Choice가 선택되어진 경우만 수행한다. # Publish 단계에선 DB정보가 완성되어 있다(ScanInfo.py에서 이미 데이터를 넣는다) ################################################################ # shotname을 기준으로 데이터베이스에 질의해서 db_shot_record에 값을 담는다. ################################################################ db_shot_record = self.datastore.getShotFromName(row[const.COLUMN_SHOTLIST]).first() if db_shot_record == None: # 데이터가 없음을 알리고 루프를 반복한다. 물론 그럴리는 없겠지만... # 별도의 처리를 하기 전까지는 그냥 루프만 반복한다. continue # 새로운 Seq Name이나 새 Seq Number가 없으면 작업 하나 마나다. 에러 메시지 출력해주게 한다.(미정) if (None == db_shot_record.seq) or (None == db_shot_record.shotnumber): return False tmp_shot_directory = path_join(tmp_path, db_shot_record.shotname) # Dpx Size ShotMaxWidth = int(db_shot_record.width) ShotMaxHeight = int(db_shot_record.height) # Thumbnail은 항상 300으로 고정한다. thumbnail_width = 300 thumbnail_height = int(float(ShotMaxHeight) / float(ShotMaxWidth) * thumbnail_width) # Half Size half_width = ShotMaxWidth / 2 half_height = ShotMaxHeight / 2 tmp_resolution_dir = path_join(tmp_shot_directory, "%dx%d" % (ShotMaxWidth, ShotMaxHeight)) if not exists(tmp_resolution_dir): makedirs(tmp_resolution_dir) # dpx, tga, cin 등의 파일을 resolution_dir에 복사 dpx_files = glob("%s/%s/*" % (const.SCAN_ROOT, db_shot_record.shotname)) # 임시 디렉터리에 파일이 존재하면 복사하지 않게 한다. new_resolution_files = glob("%s/*" % tmp_resolution_dir) # 이미 수행되어 있는 경우 다시 복사하지 않게 한다.(퍼블리시 여부로 대체한다.) if len(dpx_files) == len(new_resolution_files): # 하나라도 값이 다르면 수행하지 않게 한다. self.Alert(u"디렉터리 %s는 이미 임시 파일이 있습니다. tmp 디렉터리를 먼저 삭제하셔야 합니다" % db_shot_record.shotname) continue #return False util.fileCopy(dpx_files, tmp_resolution_dir) # 임시 디렉터리로 복사가 완료되었으면 이름을 변경후 Nuke를 사용하여 # 썸네일 및 MOV파일을 만들어넣고 seq 폴더로 데이터를 옮긴다. if 0 == len(db_shot_record.type.strip()): # Type이 비어있는 값이면... util.changesetRecord(db_shot_record, "type", "org") newShotStereo = db_shot_record.isstereo.strip().lower() publish_dir = path_join("/", "show", const.PROJECT, "seq") # Seq, SeqNumDir, TypeDirectory, ResolutionDir, ResolutionHalfDir, ThumbnailDir SeqDir = path_join(publish_dir, db_shot_record.seq) SeqNumDir = path_join(SeqDir, "%s_%s" % (db_shot_record.seq, db_shot_record.shotnumber)) # Rule : 김희경_110804_Rule if "myWay" == const.PROJECT: SeqNumDir = path_join(SeqDir, db_shot_record.shotnumber) TypeDirectory = path_join(SeqNumDir, "plate", db_shot_record.type) # Resolution Dir Create ResolutionDir = path_join(TypeDirectory, "%dx%d" % (ShotMaxWidth, ShotMaxHeight)) ResolutionHalfDir = path_join(TypeDirectory, "%dx%d" % (ShotMaxWidth / 2, ShotMaxHeight / 2)) ThumbnailDir = path_join(TypeDirectory, "thumbnail") # 비어있는 디렉터리가 있으면 생성시킨다. for item in (SeqDir, SeqNumDir, TypeDirectory, ResolutionDir, ResolutionHalfDir, ThumbnailDir): if not exists(item): makedirs(item) ################################################################ # File Renaming Rules Define # # (선결조건 : 이름이 먼저 변경되어 있어야 함)여기에서 우선 tmp/샷네임 # 디렉터리 안에서 이름을 교체하고 썸네일과 하프 사이즈를 생성할 수 있는 # .nk, .alf 파일을 각각 만들고 os.system 메소드로 실행한다. ################################################################ stereo_type = {"l" : "_left", "r" : "_right"} dpx_files = glob("%s/*" % tmp_resolution_dir) dpx_files.sort() # 정상적인 썸네일 및 영상 파일을 만들기 위해서... start_frame_number = 101 movie_src_rename_files = dict() for dpx_item in dpx_files: movie_src_file_ext = splitext(dpx_item) # 다양한 영상 소스에 대한 대응을 하기 위해서임 # New Fille Name Dictionaries new_file_name = util.NewShotNameDict() new_file_name["SEQ"] = "%s_" % db_shot_record.seq new_file_name["SHOT_NUMBER"] = "%s_" % db_shot_record.shotnumber new_file_name["TYPE"] = "plate_%s_" % db_shot_record.type new_file_name["WIDTH"] = "%dx" % ShotMaxWidth new_file_name["HEIGHT"] = "%d" % ShotMaxHeight new_file_name["STEREO"] = "%s." % stereo_type.get(db_shot_record.isstereo, '') new_file_name["FRAME"] = "%s." % str(start_frame_number).zfill(4) new_file_name["EXT"] = "%s" % movie_src_file_ext[1][1:] # 샷 타입이 org인 경우 _plate_org를 파일 이름과 스파르타 등록네임에서 빼달라는 박성진 코디 요청 있었음 # 메일을 받았을 당시 참조 메일 없었으니 이것으로 생기는 혼선에 대해선 박성진 코디네이터에게 책임이 있음 # 2012.2.20 19:32 이상호([email protected]) if db_shot_record.type == "org": del new_file_name["TYPE"] new_file_name = "".join(new_file_name.values()) # Myway Rule # Rule Name : 김희경_110804_Rule if "myWay" == const.PROJECT: del new_file_name["SEQ"] new_file_name = "".join(new_file_name.values()) # 영상 소스 파일 이름 변경 util.fileRename(dpx_item, path_join(tmp_resolution_dir, new_file_name)) start_frame_number += 1 del new_file_name # Thumbnail 파일 생성을 위해서 tmp_resolution_dir의 내용을 리스트로 담아두고 썸네일을 생성할 때 # 사용하게 한다.(디렉토리 경로는 미리 변경해두어야 한다.) dpx_files = glob("%s/*" % tmp_resolution_dir) dpx_files.sort() # 정상적인 썸네일 및 영상 파일을 만들기 위해서... ################################################################ # 이제 파일을 복사한다. ################################################################ new_shot_name = util.NewShotNameDict() new_shot_name["SEQ"] = "%s_" % db_shot_record.seq new_shot_name["SHOT_NUMBER"] = "%s_" % db_shot_record.shotnumber new_shot_name["TYPE"] = "plate_%s_" % db_shot_record.type new_shot_name["WIDTH"] = "%dx" % int(db_shot_record.width) new_shot_name["HEIGHT"] = "%d" % int(db_shot_record.height) new_shot_name["STEREO"] = "%s" % stereo_type.get(db_shot_record.isstereo, '') # New Shot Name # 마이웨이 프로젝트인 경우 newShotName도 형식이 달라져야 한다. # Rule Name : 김희경_110804_Rule if db_shot_record.type == "org": # (박성진 코디네이터 요청. 2012/02/20) del new_shot_name["TYPE"] # 기본 모드 newShotName = "".join(new_shot_name.values()) if "myWay" == const.PROJECT: del new_shot_name["SEQ"] newShotName = "".join(new_shot_name.values()) util.tmpPathToDestPath.tmp_path = tmp_shot_directory util.tmpPathToDestPath.dst_path = TypeDirectory # 디렉터리 경로를 임시 변환하게 하기 위하여 map을 호출하여 임시 경로를 새 경로로 # 변경하게 한다. dpx_files = map(util.tmpPathToDestPath, dpx_files) middle_frame = len(dpx_files) / 2 # Thumbnail File Name(Half, Thumbnail) Thumbnail_FileName = "%s.jpg" % splitext(basename(dpx_files[middle_frame]))[0] newFrameInfo = util.getNewFrame(tmp_resolution_dir) if exists(tmp_shot_directory): # 이동할 리스트를 생성한다. copy_list = glob("%s/*/*" % tmp_shot_directory) # 실제 파일을 move 시킨다. util.fileMove(copy_list, TypeDirectory) self.writePublishInfo( path_join(TypeDirectory, "%s.mov" % newShotName), path_join(ThumbnailDir, Thumbnail_FileName), ResolutionDir, newFrameInfo, db_shot_record ) # DB에도 정보가 기록이 완료되면 tmp 디렉터리도 삭제한다. rmtree(tmp_shot_directory) ################################################################ # 썸네일과 MOV 생성(MOV는 Nuke Run) ################################################################ # nuke, alfredo 스크립트 파일과 임시 MOV를 생성하게 위한 디렉터리를 생성한다. # alf, nk 파일 보관용 tmp_mov_directory = path_join(TypeDirectory, ".%.2f" % time.time()) if not exists(tmp_mov_directory): makedirs(tmp_mov_directory) # Half Image, Thumbnail Image # (스테레오 샷은 스파르타 업로드 시 걸러지므로 여기에선 스테레오 여부를 무시하고 썸네일을 생성하게 한다) JpegNuke = path_join(tmp_mov_directory, "%s_jpeg.nk" % newShotName) MovNuke = path_join(tmp_mov_directory, "%s_mov.nk" % newShotName) thumb_fd = open(const.watch_thumb_file, "a") thumb_fd.write("%s\t%s\t%s\t%s\n" % (thumbnail_width, thumbnail_height, dpx_files[middle_frame], path_join(ThumbnailDir, Thumbnail_FileName))) thumb_fd.close() time.sleep(1) # 영상 소스의 확장자 얻어오기 movie_src_ext = splitext(dpx_files[0])[1] # [MOV] 생성하기(Jpeg 생성, MOV 생성) nuke_helper.nuke_run( path_join(ResolutionDir, "%s.%%04d%s" % (newShotName, movie_src_ext)), db_shot_record.clipname, newShotName, 1024, # 확인용 720, # 확인용 '%d-%d' % (newFrameInfo["START"], newFrameInfo["END"]), path_join(tmp_mov_directory, "%s.%%04d.jpg" % newShotName), JpegNuke, path_join("/local", "%s.mov" % newShotName), True, MovNuke ) MovAlfred = tractor_script.tractorSubmission( ( '<ScanDataTransfer> MOV - %s' % newShotName, newFrameInfo["START"], newFrameInfo["END"], JpegNuke, '/bin/mv %s %s' % ( path_join("/local", "%s.mov" % newShotName), path_join(TypeDirectory, "%s.mov" % newShotName) ), MovNuke, tmp_mov_directory, path_join(TypeDirectory, "._%s.mov" % newShotName) ), True) open(path_join(tmp_mov_directory, "%s.alf" % newShotName), "w").write(MovAlfred) # AlfredRunning tractor_script.tractor_running(path_join(tmp_mov_directory, "%s.alf" % newShotName)) self.datastore.shotSave(db_shot_record) gui_util.updateProjectShots(self.datastore) self.Alert("Publish가 모두 완료되었습니다.")
def makeDBList(datastore): edl_file = path_join(const.SCAN_ROOT, "scan_%s_list.edl" % const.SCAN_DATE) boolEDLInfo = False if exists(edl_file): # EDL 파일이 있는 경우 먼저 읽어낸다. # EDL 리스트 판별(디지털인지? 필름인지?) edl_parse = None if util.edl_type(edl_file) == "Digital": edl_parse = util.EDL_Parse(edl_file) else: edl_parse = util.EDLFilm(edl_file) edl_struct = edl_parse.load() boolEDLInfo = True # Tree로부터 정보를 먼져 가져온다 shots_detail = getTreeviewShotNames() # Type은 사용자가 입력. 기본 org, 나머지 src1, src2 등이 있을 수 있음 # ISStereo는 스테레오 여부로 L, R 2 종 하나 if boolEDLInfo: # EDL로부터 읽어낸 정보가 있으면... edl_struct_keys = edl_struct.keys() edl_struct_keys.sort() for key in edl_struct_keys: values = edl_struct[key] # 개별 레코드에 관한 데이터를 가져온다. db_shot_record = datastore.getShotEDL(values['EDLNum']).first() if db_shot_record == None: db_shot_record = ScanTbl() util.changesetRecord(db_shot_record, 'ispublish', 'N') util.changesetRecord(db_shot_record, 'isstereo', '') util.changesetRecord(db_shot_record, 'project', const.PROJECT) util.changesetRecord(db_shot_record, 'scanroot', const.SCAN_ROOT) util.changesetRecord(db_shot_record, 'edlnum', values["EDLNum"]) util.changesetRecord(db_shot_record, 'reelname', values["ReelName"]) util.changesetRecord(db_shot_record, 'rolenumber', values["RoleNumber"]) util.changesetRecord(db_shot_record, 'clipname', values["ClipName"]) util.changesetRecord(db_shot_record, 'firstkeycode', values["FirstKeyCode"]) util.changesetRecord(db_shot_record, 'lastkeycode', values["LastKeyCode"]) util.changesetRecord(db_shot_record, 'filmstart', values["FilmStart"]) util.changesetRecord(db_shot_record, 'filmend', values["FilmEnd"]) util.changesetRecord(db_shot_record, 'duration', values["Duration"]) # 디렉터리명이 ReelName인 경우도 있고 EDLNum인 경우가 있을 수 있으므로 2가지 경우 모두에 대한 처리를 한다. if shots_detail.likes(values["ReelName"]) or values["EDLNum"] in shots_detail.keys(): # ReelName이 있으면 앞, 뒤 키코드를 가지고 Duration과 비교하여 정보를 삽입한다. if not values.get("useFilm", "Digital"): f_keycode = util.Keycode(values["FirstKeyCode"]) l_keycode = util.Keycode(values["LastKeyCode"]) calc_duration = l_keycode - f_keycode if not values.get("useFilm", "Digital"): detail_info = getTreeShotExists(values["ReelName"], l_keycode.minusFrame) if not detail_info: detail_info = getTreeShotExists(values["EDLNum"], l_keycode.minusFrame) else: detail_info = getTreeShotExists(values["EDLNum"], 0) if detail_info: util.changesetRecord(db_shot_record, 'shotname', detail_info["ReelName"]) util.changesetRecord(db_shot_record, 'originalstartframe', detail_info["OrgStartFrame"]) util.changesetRecord(db_shot_record, 'originalendframe', detail_info["OrgEndFrame"]) util.changesetRecord(db_shot_record, 'newstartframe', detail_info["NewStartFrame"]) util.changesetRecord(db_shot_record, 'newendframe', detail_info["NewEndFrame"]) util.changesetRecord(db_shot_record, 'starttime', detail_info["Start"]) util.changesetRecord(db_shot_record, 'endtime', detail_info["End"]) util.changesetRecord(db_shot_record, 'fps', detail_info["Fps"]) util.changesetRecord(db_shot_record, 'width', detail_info["Width"]) util.changesetRecord(db_shot_record, 'height', detail_info["Height"]) util.changesetRecord(db_shot_record, 'ratio', detail_info["Aspect"]) util.changesetRecord(db_shot_record, 'fileformat', detail_info["Format"]) util.changesetRecord(db_shot_record, 'filesize', detail_info["FileSize"]) util.changesetRecord(db_shot_record, 'seqcount', detail_info["FileCount"]) #util.changesetRecord(db_shot_record, 'ispublish', 'N') # EDL이 들어오기 전에 생성된 데이터가 있는지 살펴본다. old_shot_record = datastore.getShotFromName(detail_info["ReelName"]).first() if old_shot_record: # 예전 레코드에 새로운 레코드값을 업데이트 old_shot_record.update(db_shot_record) datastore.shotSave(old_shot_record) # 그리고 루프의 처음으로..(새로운 값 입력을 막기 위해서..) continue # DB에 정보 추가 datastore.shotSave(db_shot_record) if boolEDLInfo == False: for row in ListStore.projShotStore: # 개별 레코드에 관한 데이터를 가져온다. db_shot_record = datastore.getShotFromName(row[const.COLUMN_SHOTLIST]).first() if db_shot_record == None: db_shot_record = ScanTbl() util.changesetRecord(db_shot_record, 'isstereo', '') util.changesetRecord(db_shot_record, 'project', const.PROJECT) util.changesetRecord(db_shot_record, 'scanroot', const.SCAN_ROOT) util.changesetRecord(db_shot_record, 'shotname', row[const.COLUMN_SHOTLIST]) util.changesetRecord(db_shot_record, 'originalstartframe', row[const.COLUMN_ORG_START_FRAME]) util.changesetRecord(db_shot_record, 'originalendframe', row[const.COLUMN_ORG_END_FRAME]) util.changesetRecord(db_shot_record, 'starttime', row[const.COLUMN_START]) util.changesetRecord(db_shot_record, 'endtime', row[const.COLUMN_END]) util.changesetRecord(db_shot_record, 'fps', row[const.COLUMN_SPEED]) util.changesetRecord(db_shot_record, 'width', row[const.COLUMN_WIDTH]) util.changesetRecord(db_shot_record, 'height', row[const.COLUMN_HEIGHT]) util.changesetRecord(db_shot_record, 'ratio', row[const.COLUMN_ASPECT]) util.changesetRecord(db_shot_record, 'fileformat', row[const.COLUMN_FORMAT]) util.changesetRecord(db_shot_record, 'filesize', row[const.COLUMN_CAPACITY]) util.changesetRecord(db_shot_record, 'seqcount', row[const.COLUMN_COUNT]) util.changesetRecord(db_shot_record, 'duration', row[const.COLUMN_DURATION]) datastore.shotSave(db_shot_record)
def ExcelMigration(self, xml_file): book = ExcelBook.fromFile(xml_file) sheet = book.sheets[u'시트1'] for item in range(2, len(sheet) + 1): row = sheet[item] cellShotName = util.ExcelCellToValue(row.cells, const.EXCEL_COLUMN_SHOTNAME, '') cellSeq = util.ExcelCellToValue(row.cells, const.EXCEL_COLUMN_SEQ, '') cellShotNumber = util.ExcelCellToValue(row.cells, const.EXCEL_COLUMN_SHOTNUMBER, '') cellType = util.ExcelCellToValue(row.cells, const.EXCEL_COLUMN_TYPE, '') cellISStereo = util.ExcelCellToValue(row.cells, const.EXCEL_COLUMN_ISSTEREO, '') cellStartHandle = util.ExcelCellToValue(row.cells, const.EXCEL_COLUMN_START_HANDLE, '') cellEndHandle = util.ExcelCellToValue(row.cells, const.EXCEL_COLUMN_END_HANDLE, '') cellWidth = util.ExcelCellToValue(row.cells, const.EXCEL_COLUMN_WIDTH, '') cellHeight = util.ExcelCellToValue(row.cells, const.EXCEL_COLUMN_HEIGHT, '') cellFps = util.ExcelCellToValue(row.cells, const.EXCEL_COLUMN_FPS, '') cellFileSize = util.ExcelCellToValue(row.cells, const.EXCEL_COLUMN_FILESIZE, '') # 개별 레코드에 관한 데이터를 가져온다. db_shot_record = self.store.getShotFromName(cellShotName).first() if db_shot_record == None: db_shot_record = ScanTbl() util.changesetRecord(db_shot_record, "project", const.PROJECT) util.changesetRecord(db_shot_record, "scanroot", const.SCAN_ROOT) util.changesetRecord(db_shot_record, "shotname", cellShotName) util.changesetRecord(db_shot_record, 'isstereo', cellISStereo) util.changesetRecord(db_shot_record, 'seq', cellSeq) if "0000" != util.strtofill(cellShotNumber): util.changesetRecord(db_shot_record, 'shotnumber', util.strtofill(cellShotNumber)) util.changesetRecord(db_shot_record, 'type', cellType) util.changesetRecord(db_shot_record, 'isstereo', cellISStereo) util.changesetRecord(db_shot_record, 'fps', cellFps) util.changesetRecord(db_shot_record, 'filesize', cellFileSize) # 새로운 Seq가 없을때에는 더 이상 작업을 진행할 필요가 없다. if 1 > len(cellSeq): continue # 2011.07 이전의 스캔 데이터 트랜스퍼에서는 cellShotNumber가 0으로 채워진 일련번호(4자리)이다. cellShotNumber = util.strtofill(cellShotNumber) cellWidth = util.strtofill(cellWidth, 0) cellHeight = util.strtofill(cellHeight, 0) util.changesetRecord(db_shot_record, 'width', cellWidth) util.changesetRecord(db_shot_record, 'height', cellHeight) # Directory Exists projDirectory = '/'.join(xml_file.split('/')[:-4]) seqDirectory = path_join(projDirectory, "seq", cellSeq) seqNumDirectory = path_join(seqDirectory, "%s_%s" % (cellSeq, cellShotNumber)) plateDirectory = path_join(seqNumDirectory, "plate", cellType) resDirectory = path_join(plateDirectory, "%sx%s" % (str(cellWidth), str(cellHeight))) ThumbFile = glob("%s/thumbnail/*.jpg" % (plateDirectory)) if len(ThumbFile) > 0: ThumbFile = ThumbFile[0] MovFile = glob("%s/*.mov" % plateDirectory) if len(MovFile) > 0: MovFile = MovFile[0] if exists(plateDirectory): # 여기서 채워지지 않은 정보는 EDL 리스트를 재구축하면서 채워지게 된다. util.changesetRecord(db_shot_record, 'ispublish', 'Y') util.changesetRecord(db_shot_record, 'movpath', MovFile) util.changesetRecord(db_shot_record, 'jpgpath', ThumbFile) util.changesetRecord(db_shot_record, 'publishpath', resDirectory) # DB Save self.store.shotSave(db_shot_record) # xml file이 있는 경우 삭제한다.(마이그레이션 작업이 완료되었으므로..) - 하지만 일단 테스트를 위해 지우지는 않는다. # 대신에 나중에 다시 사용할 수 있을 것 같으므로 정보를 보존한다. if exists(xml_file): #unlink(xml_file) #pass rename(xml_file, xml_file.replace(".xml", "_MigComplete.xml"))