Beispiel #1
0
	def clkSpartaUploadClear(self, widget, event, data=None):
		for list_row in ListStore.projShotStore:
			row_selected = list_row[const.COLUMN_CHOICE]
			row_register = list_row[const.COLUMN_REGISTER]
			
			if row_selected and 'Y' == row_register:
				shot_name = list_row[const.COLUMN_SHOTLIST]
				db_shot_record = self.datastore.getShotFromName(shot_name).first()
				
				# 업로드 여부 지움
				db_shot_record.isregister = u'N'
				self.datastore.shotSave(db_shot_record)
		
		gui_util.updateProjectShots(self.datastore)
Beispiel #2
0
	def clkInfoXlsLoad(self, widget, event, data=None):
		# infoXLS 불러오기 클릭시 

		# 다이얼로그 오픈 ---------------------        
		FileDialog = gtk.FileChooserDialog("Open info.xls Path", self.parentWindow,
                                           gtk.FILE_CHOOSER_ACTION_OPEN,
                                           (gtk.STOCK_CANCEL,
                                            gtk.RESPONSE_CANCEL,
                                            gtk.STOCK_OPEN,
                                            gtk.RESPONSE_OK
                                           ),
                                           None)

		FileDialog.set_default_response(gtk.RESPONSE_OK)

		filter = gtk.FileFilter()
		filter.set_name("info.xls")
		filter.add_pattern("*.xls")

		FileDialog.add_filter(filter)        
		FileDialog.show()

		response = FileDialog.run()        

		if response == gtk.RESPONSE_OK:
			filename = FileDialog.get_filename()
			FileDialog.destroy()
		else:
			FileDialog.destroy()
			return
		# ------------------------------------
                       		
		# 엑셀에서 셀값을 가져와 딕셔너리에 저장 ----------------
		book = xlrd.open_workbook( filename ) 
		sh = book.sheet_by_index(0)

		ShotMatchDict = dict()				
		for record_index in range( 1, sh.nrows ): # 2번재 줄부터 읽음 
			DirName 	= str(sh.cell_value(record_index, 0))
			SeqName 	= str(sh.cell_value(record_index, 1))
			SeqNumber 	= str(sh.cell_value(record_index, 2))
			ShotType 	= str(sh.cell_value(record_index, 3))
			ShotStereo 	= str(sh.cell_value(record_index, 4))

			if len(re.findall("\.[0-9]+$",DirName)) > 0: # Add By Sabzil
				DirName = DirName.split(".")[0]

			ShotMatchDict[DirName] = {
				"SeqName" :   	SeqName,
				"SeqNumber" : 	SeqNumber,
				"ShotType" : 	ShotType,
				"ShotStereo" :  ShotStereo
			}

		# -------------------------------------------------------
		
		# ShotName이 중복해서 있는 경우는 뒤에 _를 붙여주어야 한다.
		# 이 요구사항은 코디네이터 김희경님의 요청사항이다(마이웨이 하나 때문에 이것저것 처리해둔다)
		# Rule Name : 김희경_110804_Rule

		#print ShotMatchDict

		ShotNameDuplicate = {}
		ShotNumber = ""

		# 엑셀에 표기된 SeqName, SeqNum 대로 찾아서, 뒷부분에 숫자가 있을경우 그 숫자를 Duplicate에 기록한다.
		# [WARNNING] 전 개발자가, SeqNumber라고 표현 했지만, 원래는 샷이름임
		for (key, value) in ShotMatchDict.items():
			# /show/myWay/seq/SeqNAME/SeqNUM
			dir_list = glob("%s*" % path_join("/", "show", const.PROJECT, "seq", value["SeqName"], value["SeqNumber"]))
			dir_list.sort()

			if len(dir_list) > 0:
				numTail = re.findall("([0-9]+)$", dir_list[-1] )
				if len(numTail) > 0:
					ShotNameDuplicate[ value.get("SeqNumber") ] = numTail[0] # 다시 채킹필요
				elif exists( dir_list[-1] ):
					ShotNameDuplicate[ value.get("SeqNumber") ] = 0
		

		#[sz] ListStore는 GTK용 오브젝트, ListData를 가지는 컨테이너

		# ListStore Update(from ShotMatchDict)
		for row in ListStore.projShotStore:

			# ShotName은 디렉터리 이름을 완전하게 매치해야 한다.
			ShotName = row[ const.COLUMN_SHOTLIST ]

			# DB정보를 가져온다.
			db_shot_record = self.datastore.getShotFromName(ShotName).first()
			if (None == db_shot_record):
				self.Alert("영상소스 파일 수와 키코드 계산 결과 프레임이 일치하지 않습니다. 데이터를 확인하여 주십시오.\n문제가 발생한 디렉터리는 %s 입니다." % ShotName)
				continue
			
			# DB의 정보를 가져온다.
			List_Seq 		= db_shot_record.seq
			List_SeqNumber  = db_shot_record.shotnumber
			List_Type 		= db_shot_record.type
			List_Stereo 	= db_shot_record.isstereo
			
			# 먼저 정보를 불러온다.
			XlsMatchDict = ShotMatchDict.get(ShotName, None)

			if XlsMatchDict == None:
				if ShotName.isdigit():					
					XlsMatchDict = ShotMatchDict.get( str(int(ShotName)) , None )

			if XlsMatchDict == None:
				print "Not Found in Excel:", ShotName
				continue

			# 정보 갱신을 위해 기존 값이 길이 0인지 확인한다.(0인 경우에만 정보를 갱신한다.)
			if (None == List_Seq) or (0 == len(List_Seq)):
				# SeqName이 숫자로만 구성되어 있는 경우 소수점으로 들어갈 수 있는 문제가 있다.
				re_search_result = re.search("^([0-9]+)\.[0-9]+$", str(XlsMatchDict["SeqName"]))
				if re_search_result:
					XlsMatchDict["SeqName"] = re_search_result.group(1)
				db_shot_record.seq = XlsMatchDict["SeqName"]
			

			if (None == List_SeqNumber) or (0 == len(List_SeqNumber)):
				# 먼저 중복된 SeqNumbner가 ShotNameDuplicate 에 있는지 확인한다.(내가 무슨 잘못을...)
				# 먼저 엑셀의 데이터를 기준으로 마이웨이 프로젝트에 한해서 디렉터리가 이미 존재하는지 확인한다.

				if XlsMatchDict["SeqNumber"] in ShotNameDuplicate:
					ShotNameDuplicate[XlsMatchDict.get("SeqNumber")] += 1
					ShotNumber = "%s_%d" % (
						XlsMatchDict["SeqNumber"],
						ShotNameDuplicate[XlsMatchDict.get("SeqNumber")]
					)

				else:
					ShotNameDuplicate[XlsMatchDict.get("SeqNumber")] = 0
					ShotNumber = XlsMatchDict["SeqNumber"]
					
					# 2011/08/12일 기존 경로인 138 디렉터리 아래 동일한 샷네임이 있을 경우 MOV영상을 덮어 써버리는 문제가 있어서
					# 기존 경로도 조사하게 한다.(단, 이 루틴은 마이웨이에 한정한다.)
					if "myWay" == const.PROJECT:
						dir_list = glob("%s*" % path_join("/", "show", const.PROJECT, "seq", XlsMatchDict["SeqName"], XlsMatchDict["SeqNumber"]))
						dir_list.sort()
						
						if len(dir_list) > 0:
							search = re.search(".+_([0-9]+)$", dir_list[-1])
							if search:
								# 기존 경로가 존재하면..
								ShotNameDuplicate[XlsMatchDict.get("SeqNumber")] = int(search.group(1))
								ShotNumber = "%s_%d" % (
									XlsMatchDict["SeqNumber"],
									ShotNameDuplicate[XlsMatchDict.get("SeqNumber")]
								)
				
				db_shot_record.shotnumber = ShotNumber
			
			if None == List_Type or 0 == len(List_Type):
				db_shot_record.type = XlsMatchDict["ShotType"]
			
			if None == List_Stereo or 0 == len(List_Stereo):
				db_shot_record.isstereo = XlsMatchDict["ShotStereo"]
			
			# DB 갱신
			self.datastore.shotSave(db_shot_record)
	
		# ListStore 갱신
		gui_util.updateProjectShots( self.datastore )

		return 
Beispiel #3
0
	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가 모두 완료되었습니다.")
Beispiel #4
0
    def cbPrjDateChange(self, combobox, user_param1):
        if combobox.get_active_text() == u"스캔 데이터가 없습니다":
            return False
        
        scan_root_path = path_join("/", "show", const.PROJECT, "product", "scan", combobox.get_active_text())
        
        const.SCAN_DATE = combobox.get_active_text()
        const.SCAN_ROOT = scan_root_path
        ListStore.projShotStore.clear()
        
        # Scan Shot List Output
        if self.projScanRootDirs == None:
            
            shot_lists = glob( path_join(const.SCAN_ROOT, "*") )
            shot_lists.sort()
            
            self.projScanRootDirs = shot_lists
        
        # Djv Info 객체 생성
        djv_info = DjvInfo( const.SCAN_ROOT )

        for item in self.projScanRootDirs:
            if isdir(item) and basename(item) not in ("tmp", "mov"):
                print "item", item                
                # ScanRoot안에 0개의 파일을 가진 디렉터리가 존재하면 리스트에 추가할 수 없으므로 루프를 반복시킨다.
                if 0 == len( glob("%s/*" % item) ):
                    continue
                
                # 디렉터리 안에 unknown.txt가 있으면 작업하지 않게 한다.
                if exists(path_join(item, "unknown.txt")):
                    continue
                
                djv_information = {}
                djv_files_size = None
                orginalFrameInfo = {}
                seq_count = 0

                # 샷의 정보가 DB에 있는지 먼저 확인해서 있으면 아래 과정을 반복하게 하지 않는다.(정말 오래 걸린다. 용량을 산정하기 때문에..)
                db_shot_record = self.store.getShotFromName(basename(item)).first()
                if None == db_shot_record:
                    djv_information = djv_info.retrieveInfo(item)
                    djv_files_size = util.approximate_size(djv_info.total_size(item), False)
                    orginalFrameInfo = util.getOriginalFrame(basename(item))
                    
                    seq_count = len(glob(path_join(const.SCAN_ROOT, item, "*")))
                else:
                    djv_information['Start'] = db_shot_record.starttime or ''
                    djv_information['End'] = db_shot_record.endtime or ''
                    djv_information['Duration'] = db_shot_record.duration or ''
                    djv_information['Speed'] = db_shot_record.fps or ''
                    djv_information['Width'] = db_shot_record.width or ''
                    djv_information['Height'] = db_shot_record.height or ''
                    djv_information['Aspect'] = db_shot_record.ratio or ''
                    
                    orginalFrameInfo['START'] = db_shot_record.originalstartframe or ''
                    orginalFrameInfo['END'] = db_shot_record.originalendframe or ''
                    orginalFrameInfo['EXT'] = db_shot_record.fileformat or ''
                    
                    seq_count = db_shot_record.seqcount or 0
  
                print "djv:", djv_information
                ListStore.projShotStore.append(
                    row=[
                        None,
                        basename(item),
                        '', # new seq
                        '', # new seq num
                        '', # type
                        '', # stereo
                        False, # publish
                        int(orginalFrameInfo["START"]), # original start frame
                        int(orginalFrameInfo["END"]), # original end frame
                        0, # start handle
                        0, # end handle
                        0, # new start frmae
                        0, # new end frame
                        djv_information['Start'],
                        djv_information['End'],
                        djv_information['Duration'],
                        djv_information['Speed'],
                        int(djv_information['Width']),
                        int(djv_information['Height']),
                        djv_information['Aspect'],
                        orginalFrameInfo["EXT"], # format
                        djv_files_size,
                        int(seq_count),
                        'N'
                    ]
                )
        
        gui_util.makeDBList(self.store)
        
        ## XML File이 있을 경우 Migration
        xml_file = path_join(scan_root_path, "scan_%s_list.xml" % const.SCAN_DATE)
        if exists(xml_file):
            self.ExcelMigration(xml_file)
        
        gui_util.updateProjectShots(self.store)