Guest User

Untitled

a guest
Jul 10th, 2024
415
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.32 KB | Software | 0 0
  1. # This code is generated by ChatGPT 3.5
  2. # compile .exe by Pyinstaller
  3. #pyinstaller test.py --onefile --noconsole
  4. import tkinter
  5. import tkinter.font
  6. from tkinter import ttk
  7. import tkinter.filedialog
  8. import tkinter.simpledialog
  9.  
  10. import configparser
  11. import subprocess
  12. import re
  13. import os
  14. import shutil
  15. import threading
  16. import winsound
  17. import time
  18. from smartcard.util import toHexString
  19. from smartcard.util import toBytes
  20. from smartcard.System import readers as get_readers
  21.  
  22. # dumptsGUI.ini
  23. def read_ini():
  24. config = configparser.ConfigParser()
  25. config.read('dumptsGUI.ini')
  26. default_path = config.get('Paths', 'default_path', fallback='')
  27. mpc_hc_path = config.get('Paths', 'mpc_hc_path', fallback='')
  28. mkv_path = config.get('Paths', 'mkv_path', fallback='')
  29. return default_path, mpc_hc_path, mkv_path
  30.  
  31. def write_ini(default_output_path, mpc_hc_path, mkv_path):
  32. config = configparser.ConfigParser()
  33. config['Paths'] = {'default_path': default_output_path,
  34. 'mpc_hc_path': mpc_hc_path,
  35. 'mkv_path': mkv_path}
  36. with open('dumptsGUI.ini', 'w') as configfile:
  37. config.write(configfile)
  38.  
  39. def sanitize_filename(filename):
  40. # 許可する文字:英数字、ハイフン、アンダースコア、ドット、ひらがな、カタカナ、漢字、全角スペース、全角英字数字、全角カッコ、全角カギカッコ
  41. allowed_chars = re.compile(r'[^a-zA-Z0-9._\-\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF\u3000\uFF10-\uFF19\uFF08\uFF09\u300C\u300D\uFF21-\uFF3A\uFF41-\uFF5A]')
  42. sanitized_name = allowed_chars.sub('_', filename)
  43. return sanitized_name
  44. def rename_files_in_directory(directory, filename):
  45. sanitized_name = sanitize_filename(filename)
  46. old_path = filename
  47. new_path = sanitized_name
  48. if old_path != new_path:
  49. os.rename(os.path.join(directory, old_path), os.path.join(directory, new_path))
  50. label4['text'] =f'Rename(expand): {filename} -> {sanitized_name}'
  51. else:
  52. label4['text'] =f'No change needed: {filename}'
  53. return new_path
  54.  
  55. # Program START
  56. if not os.path.exists('dumptsGUI.ini'):
  57. write_ini('', '', '')
  58. # Load paths from ini file
  59. default_path, mpc_hc_path, mkv_path = read_ini()
  60.  
  61. readers = get_readers()
  62. print(readers)
  63.  
  64. # Main window
  65. main_win = tkinter.Tk()
  66. main_win.title("DumpTS GUI, code generated by ChatGPT")
  67. main_win.geometry("700x400")
  68.  
  69. # Main frame
  70. main_frm = ttk.Frame(main_win)
  71. main_frm.grid(column=0, row=0, sticky=tkinter.NSEW, padx=5, pady=10)
  72.  
  73. if len(readers)!=0:
  74. conn = readers[0].createConnection()
  75. try:
  76. conn.connect()
  77. recv_data=conn.getATR()
  78. print(toHexString(recv_data))
  79.  
  80. # widget line 1
  81. label1 = ttk.Label(main_frm,text=readers, foreground='orange', background='black')
  82.  
  83.  
  84. # widget line 2
  85. label2 = ttk.Label(main_frm,text=toHexString(recv_data), foreground='orange', background='black')
  86.  
  87. if toHexString(recv_data[:4]) == '3B F0 13 00':
  88. # 4バイトが一致する場合の処理
  89. label2 ['text']= toHexString(recv_data)
  90. pass
  91. else:
  92. label2 ['text']= "Error: Confirm/Re-insert IC card"
  93. except:
  94. print('No card')
  95. label1 = ttk.Label(main_frm,text='No card', foreground='red', background='black')
  96. label2 = ttk.Label(main_frm,text=' ', foreground='orange', background='black')
  97.  
  98. else:
  99. label1 = ttk.Label(main_frm,text='No IC readers', foreground='red', background='black')
  100. label2 = ttk.Label(main_frm,text=' ', foreground='orange', background='black')
  101.  
  102.  
  103.  
  104. def btnReconnect_click():
  105. global readers,conn
  106. readers = get_readers()
  107. conn = readers[0].createConnection()
  108. conn.connect()
  109. recv_data=conn.getATR()
  110. label1 ['text'] =readers
  111. if toHexString(recv_data[:4]) == '3B F0 13 00':
  112. # 4バイトが一致する場合の処理
  113. label2 ['text']= toHexString(recv_data)
  114. pass
  115. else:
  116. label2 ['text']= "Error: Confirm/Re-insert IC card"
  117. main_win.mainloop()
  118.  
  119. def select_file_and_run():
  120. global selected_file, AACmatches, HEVCmatches
  121. # ファイル選択ダイアログを表示し、ユーザからファイル名を取得
  122. selected_file = tkinter.filedialog.askopenfilename()
  123. directory = os.path.dirname(selected_file)
  124. if selected_file:
  125. selected_filename =rename_files_in_directory(directory, os.path.basename(selected_file) )
  126. selected_file= os.path.join(directory, selected_filename)
  127. # 選択されたファイル名とファイルパスを表示
  128. label_selected_file['text'] = f"Selected File: {selected_filename}\nFile Path: {selected_file}"
  129.  
  130. # Dumpts.exeを実行し、選択されたファイル名を引数に渡す
  131. result = subprocess.run(["Dumpts.exe", selected_file, "--MAXMB=100", "--CID=1", "--showinfo"], stdout=subprocess.PIPE)
  132.  
  133. if result.stdout is not None:
  134. # 出力を取得して処理する
  135. output_lines = result.stdout.decode('utf-8').splitlines()
  136. last_25_lines = '\n'.join(output_lines[-26:])
  137. label5['text'] = last_25_lines
  138.  
  139. # パターンにマッチする部分を検索
  140. pattern = r"CID: (0x[0-9A-F]+), packet_id: (0x[0-9A-F]+).*HEVC Video Stream"
  141. HEVCmatches = re.findall(pattern, last_25_lines)
  142. cid, packet_id = HEVCmatches[0]
  143. label5['text'] = f"HEVC Video Stream: CID: {cid}, packet_id: {packet_id}\n"
  144.  
  145. pattern = r"CID: (0x[0-9A-F]+), packet_id: (0x[0-9A-F]+).*MPEG-4 AAC Audio Stream"
  146. AACmatches = re.findall(pattern, last_25_lines)
  147. for match in AACmatches:
  148. cid, packet_id = match[0], match[1]
  149. label5['text'] += f"MPEG-4 AAC Audio Stream: CID: {cid}, packet_id: {packet_id}\n"
  150. else:
  151. label5['text'] = "Error: Unable to retrieve output from Dumpts.exe"
  152.  
  153. def btnGetKey_click():
  154. global selected_file, AACmatches, HEVCmatches
  155. result = subprocess.run(["Dumpts.exe", "8k.mmts", "--MAXMB=100", "--CID=1", "--showinfo"], stdout=subprocess.PIPE)
  156.  
  157. if result.stdout is not None:
  158. output_lines = result.stdout.decode('utf-8').splitlines() # バイナリデータをUTF-8でデコードして行に分割
  159. last_25_lines = '\n'.join(output_lines[-26:]) # 最後の25行を取得
  160. label5['text'] = last_25_lines
  161. # パターンにマッチする部分を検索
  162. # テキストからCIDとpacket_idを抽出する正規表現パターン
  163. pattern = r"CID: (0x[0-9A-F]+), packet_id: (0x[0-9A-F]+).*HEVC Video Stream"
  164. # 正規表現パターンにマッチする全てのCIDとpacket_idのペアを抽出
  165. HEVCmatches = re.findall(pattern, last_25_lines)
  166. # HEVC Video StreamとMPEG-4 AAC Audio StreamのCIDとpacket_idの値を取得
  167. cid, packet_id = HEVCmatches[0]
  168. print(f"HEVC Video Stream: CID: {cid}, packet_id: {packet_id}")
  169. pattern = r"CID: (0x[0-9A-F]+), packet_id: (0x[0-9A-F]+).*MPEG-4 AAC Audio Stream"
  170. # 正規表現パターンにマッチする全てのCIDとpacket_idのペアを抽出
  171. AACmatches = re.findall(pattern, last_25_lines)
  172. for match in AACmatches:
  173. cid, packet_id = match[0], match[1]
  174. print(f"MPEG-4 AAC Audio Stream: CID: {cid}, packet_id: {packet_id}")
  175.  
  176.  
  177. else:
  178. label5['text'] = "Error: Unable to retrieve output from AA.exe"
  179. main_win.mainloop()
  180.  
  181. def btnWriteID_click():
  182. global AACmatches, HEVCmatches,output_filename, default_path, mpc_hc_path, use_sleep_ms
  183.  
  184. # 選択されたファイルがない場合は処理を中止
  185. if not selected_file:
  186. label5['text'] = "Error: No file selected"
  187. return
  188. # プログラムの実行場所を取得
  189. current_directory = os.getcwd()
  190. # デフォルトのパスを使用するか、iniファイルから読み込んだパスを使用するかを決定する
  191. current_directory = default_path if default_path else current_directory
  192. default_output_path = os.path.join(current_directory, f"out_{os.path.basename(selected_file)}")
  193. # ファイル名の入力を取得
  194. output_filename = default_output_path#tkinter.simpledialog.askstring("Input", "Enter the output filename:", initialvalue=default_output_path)
  195. if not output_filename:
  196. label5['text'] = "Error: No output filename entered"
  197. return
  198.  
  199. # mmtsファイルの頭の〇〇MBをSkipして処理する。デフォルト値は0 MB
  200. input_value = numeric_input.get()
  201. if input_value.strip(): # 空でない文字列であるかどうかを確認
  202. skip_bytes = int(input_value)
  203. else:
  204. # エラー処理またはデフォルト値の設定などを行う
  205. skip_bytes = int(0) # 例えば、デフォルト値として0を設定
  206.  
  207. # SleepMSの設定
  208. sleep_ms = 0 if not use_sleep_ms else 200
  209.  
  210.  
  211. # Dumpts.exe 実行のためのパケット ID リストを初期化
  212. packet_ids = []
  213.  
  214. # HEVC パケット ID を取得
  215. for cid, packet_id in HEVCmatches:
  216. packet_ids.append(packet_id)
  217.  
  218. # AAC パケット ID を取得
  219. for cid, packet_id in AACmatches:
  220. packet_ids.append(packet_id)
  221. # パケット ID を & でつなげる
  222. packet_ids_str = "&".join(packet_ids)
  223.  
  224. process = subprocess.Popen(["Dumpts.exe", selected_file, f"--SleepMS={sleep_ms}", f"--SKIPMB={skip_bytes}", f"--CID={cid}", f"--pid={packet_ids_str}", f"--output={output_filename}"], stdout=subprocess.PIPE)
  225. label4['text'] = "DumpTS.exe is running..."
  226.  
  227. # パスをiniファイルに保存
  228. write_ini(current_directory, mpc_hc_path,mkv_path)
  229.  
  230. # ファイルサイズの変化をチェックするスレッドを開始
  231. check_size_thread = threading.Thread(target=check_file_size)
  232. check_size_thread.start()
  233.  
  234. def check_file_size():
  235. global output_filename, HEVCmatches
  236. output_filename_without_extension = output_filename.rsplit('.', 1)[0]
  237. # 映像ファイルのパスを生成
  238. video_file_path = f"{output_filename_without_extension}_{HEVCmatches[0][1]}.{output_filename.rsplit('.', 1)[1]}"
  239. time.sleep(10)
  240. # 初期のファイルサイズを取得
  241. initial_size = os.path.getsize(video_file_path)
  242.  
  243. while True:
  244. # 10秒待機
  245. time.sleep(10)
  246. # 現在のファイルサイズを取得
  247. current_size = os.path.getsize(video_file_path)
  248. # ファイルサイズが変化しなくなった場合
  249. if current_size == initial_size:
  250. # "DumpTS.exe Completed"とラベルを更新
  251. label4['text'] = "DumpTS.exe Completed"
  252. # 効果音を鳴らす
  253. winsound.PlaySound("SystemExit", winsound.SND_ALIAS)
  254. break
  255. else:
  256. initial_size =current_size
  257.  
  258. # チェックボックスの状態を格納する変数
  259. use_sleep_ms = tkinter.BooleanVar()
  260. use_sleep_ms.set(False) # デフォルトでチェックされていない
  261.  
  262. # チェックボックスのコールバック関数
  263. def on_checkbox_clicked():
  264. global use_sleep_ms
  265. use_sleep_ms = not use_sleep_ms
  266.  
  267. # チェックボックスの作成
  268. checkbox = ttk.Checkbutton(main_frm, text="ACAS排他モード", variable=use_sleep_ms, command=on_checkbox_clicked)
  269. checkbox.grid(column=0, row=4, pady=10)
  270.  
  271. label_numeric_input = ttk.Label(main_frm, text="チェックしてからDumpTSを実行すると、ACAS ICを占有して高速処理する (他のアプリでACAS ICを使えません)")
  272. label_numeric_input.grid(column=1, row=4, sticky=tkinter.EW, padx=5)
  273.  
  274. def playFile_click():
  275. global output_filename, HEVCmatches, AACmatches, default_path, mpc_hc_path
  276. if output_filename and HEVCmatches and AACmatches:
  277. try:
  278. output_filename_without_extension = output_filename.rsplit('.', 1)[0]
  279. # 映像ファイルのパスを生成
  280. video_file_path = f"{output_filename_without_extension}_{HEVCmatches[0][1]}.{output_filename.rsplit('.', 1)[1]}"
  281.  
  282. # 音声ファイルのパスを生成(AACmatchesの2つ目のパケットIDを使用)
  283. original_audio_file_path = f"{output_filename_without_extension}_{AACmatches[0][1]}.{output_filename.rsplit('.', 1)[1]}"
  284. #renamed_audio_file_path = f"{output_filename_without_extension}_{AACmatches[0][1]}.dts"
  285. #shutil.copyfile(original_audio_file_path, renamed_audio_file_path)
  286. mpc_hc_path_ini=mpc_hc_path
  287. # mpc-hc64.exe のパスを取得
  288. mpc_hc_path = "C:\\Program Files\\MPC-HC\\mpc-hc64.exe"
  289. # デフォルトのパスを使用するか、iniファイルから読み込んだパスを使用するかを決定する
  290. mpc_hc_path = mpc_hc_path_ini if mpc_hc_path_ini else mpc_hc_path
  291.  
  292. # mpc-hc64.exe を実行し、映像ファイルと音声ファイルのパスを引数として渡す
  293. subprocess.Popen([mpc_hc_path, video_file_path])#subprocess.run([mpc_hc_path, video_file_path, f"/dub \"{renamed_audio_file_path}\""])
  294. #subprocess.Popen([mpc_hc_path, original_audio_file_path ])
  295.  
  296. # 実行成功時のメッセージを表示
  297. play_file_label['text'] = "MPC-HC has been executed successfully"
  298. mpc_hc_path_label['text'] = f"MPC-HC Location: {mpc_hc_path}"
  299. except FileNotFoundError:
  300. # ファイルが見つからない場合のエラーメッセージを表示
  301. play_file_label['text'] = "Error: MPC-HC not found"
  302. else:
  303. # 必要なファイルやマッチが見つからない場合のエラーメッセージを表示
  304. play_file_label['text'] = "Error: Missing output filename or matches"
  305. mpc_hc_path_label['text'] = ""
  306.  
  307.  
  308. def launch_mkv_tool():
  309. global mkv_path
  310. mkv_path_ini=mkv_path
  311. mkv_path = "C:\\Program Files\\MKVToolNix\\mkvtoolnix-gui.exe"
  312. mkv_path = mkv_path_ini if mkv_path_ini else mkv_path
  313. mkv_path_label.config(text=mkv_path)
  314. subprocess.Popen([mkv_path])
  315.  
  316. mkv_path_label = ttk.Label(main_frm, text='', foreground='white', background='black')
  317. mkv_path_label.grid(column=1, row=8, sticky=tkinter.EW, padx=5)
  318.  
  319. # ファイル処理ボタンの作成
  320. button_process_files_to_mkv = ttk.Button(main_frm, text="Launch MKVtoolnix", command=launch_mkv_tool)
  321. button_process_files_to_mkv.grid(column=0, row=8, pady=10)
  322.  
  323. mpc_hc_path_label= ttk.Label(main_frm, text='', foreground='white', background='black')
  324. mpc_hc_path_label.grid(column=1, row=7, sticky=tkinter.EW, padx=5)
  325. button_play_file = ttk.Button(main_frm, text="Play File", command=playFile_click)
  326. button_play_file.grid(column=0, row=6, pady=10)
  327. play_file_label= ttk.Label(main_frm, text='', foreground='white', background='black')
  328. play_file_label.grid(column=1, row=6, sticky=tkinter.EW, padx=5)
  329. # ファイル選択ボタンの作成
  330. button_select_file = ttk.Button(main_frm, text="Select File", command=select_file_and_run)
  331. button_select_file.grid(column=0, row=2, pady=10)
  332. # 選択されたファイルを表示するラベルの作成
  333. label_selected_file = ttk.Label(main_frm, text='', foreground='white', background='black')
  334. label_selected_file.grid(column=1, row=2, sticky=tkinter.EW, padx=5)
  335. # widget line 4
  336. label5 = ttk.Label(main_frm, text='', foreground='white', background='black')
  337.  
  338. # widget line 1
  339. label3 = ttk.Label(main_frm,text='Card Reader')
  340.  
  341. # widget line 2
  342. buttonA = ttk.Button(
  343. main_frm, text = 'Re-analyze file', command=btnGetKey_click)
  344.  
  345. # widget line 3
  346. buttonB = ttk.Button(
  347. main_frm, text = 'DumpTS', command=btnWriteID_click)
  348.  
  349. # widget line 3
  350. label4 = ttk.Label(main_frm, text='Select mmts file, then click DumpTS', foreground='white', background='black')
  351.  
  352. # widget line 4
  353. buttonC = ttk.Button(
  354. main_frm, text = 'Connect IC card', command=btnReconnect_click)
  355.  
  356.  
  357. label3.grid(column=0, row=0, pady=10)
  358. label1.grid(column=1, row=0, sticky=tkinter.EW, padx=5)
  359. buttonA.grid(column=0, row=5)
  360. label2.grid(column=1, row=1, sticky=tkinter.EW, padx=5)
  361. buttonB.grid(column=0, row=3, pady=10)
  362. label4.grid(column=1, row=3, sticky=tkinter.EW, padx=5)
  363. buttonC.grid(column=0, row=1, pady=10)
  364. label5.grid(column=1, row=5, sticky=tkinter.EW, padx=5)
  365.  
  366. # 数値入力フィールドを追加
  367. label_numeric_input = ttk.Label(main_frm, text="(MB, Option):SKIP the first XXXMB of mmts file, if file can't play")
  368. label_numeric_input.grid(column=1, row=9, sticky=tkinter.EW, padx=5)
  369. numeric_input = ttk.Spinbox(main_frm, from_=0, to=10000)
  370. numeric_input.grid(column=0, row=9, pady=10)
  371.  
  372. # place settings
  373. main_win.columnconfigure(0, weight=1)
  374. main_win.rowconfigure(0, weight=1)
  375. main_frm.columnconfigure(1, weight=1)
  376. main_win.mainloop()
  377.  
  378.  
  379.  
Advertisement
Add Comment
Please, Sign In to add comment