You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1189 lines
42 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. #! /usr/bin/env python
  2. '''
  3. This file contains all gui classes
  4. MainFrame
  5. Custom wx.ListCtrl class
  6. OptionsFrame
  7. GeneralPanel
  8. AudioPanel
  9. ConnectionPanel
  10. VideoPanel
  11. FilesystemPanel
  12. SubtitlesPanel
  13. OtherPanel
  14. UpdatePanel
  15. AuthenticationPanel
  16. PlaylistPanel
  17. '''
  18. import wx
  19. from wx.lib.pubsub import setuparg1
  20. from wx.lib.pubsub import pub as Publisher
  21. from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin
  22. from .version import __version__
  23. from .UpdateThread import UpdateThread
  24. from .DownloadThread import DownloadManager
  25. from .OptionsHandler import OptionsHandler
  26. from .YoutubeDLInterpreter import YoutubeDLInterpreter
  27. from .OutputHandler import DownloadHandler
  28. from .LogManager import LogManager, LogGUI
  29. from .Utils import (
  30. video_is_dash,
  31. have_dash_audio,
  32. get_os_type,
  33. file_exist,
  34. fix_path,
  35. abs_path,
  36. icon_path,
  37. remove_spaces
  38. )
  39. if get_os_type() == 'nt':
  40. YOUTUBE_DL_FILENAME = 'youtube-dl.exe'
  41. else:
  42. YOUTUBE_DL_FILENAME = 'youtube-dl'
  43. TITLE = 'Youtube-dlG'
  44. AUDIOFORMATS = ["mp3", "wav", "aac", "m4a"]
  45. VIDEOFORMATS = ["default",
  46. "mp4 [1280x720]",
  47. "mp4 [640x360]",
  48. "webm [640x360]",
  49. "flv [400x240]",
  50. "3gp [320x240]",
  51. "mp4 1080p(DASH)",
  52. "mp4 720p(DASH)",
  53. "mp4 480p(DASH)",
  54. "mp4 360p(DASH)"]
  55. DASH_AUDIO_FORMATS = ["NO SOUND",
  56. "DASH m4a audio 128k",
  57. "DASH webm audio 48k"]
  58. LANGUAGES = ["English",
  59. "Greek",
  60. "Portuguese",
  61. "French",
  62. "Italian",
  63. "Russian",
  64. "Spanish",
  65. "German"]
  66. ICON = icon_path(['icons', 'ytube.png'], __file__)
  67. class MainFrame(wx.Frame):
  68. def __init__(self, parent=None, id=-1):
  69. wx.Frame.__init__(self, parent, id, TITLE+' '+__version__, size=(600, 420))
  70. # init gui
  71. self.InitGUI()
  72. # bind events
  73. self.Bind(wx.EVT_BUTTON, self.OnDownload, self.downloadButton)
  74. self.Bind(wx.EVT_BUTTON, self.OnUpdate, self.updateButton)
  75. self.Bind(wx.EVT_BUTTON, self.OnOptions, self.optionsButton)
  76. self.Bind(wx.EVT_TEXT, self.OnTrackListChange, self.trackList)
  77. self.Bind(wx.EVT_CLOSE, self.OnClose)
  78. # set app icon
  79. icon = wx.Icon(ICON, wx.BITMAP_TYPE_ICO)
  80. self.SetIcon(icon)
  81. # set publisher for update thread
  82. Publisher.subscribe(self.update_handler, "update")
  83. # set publisher for download thread
  84. Publisher.subscribe(self.download_handler, "download")
  85. # init Options and DownloadHandler objects
  86. self.optionsList = OptionsHandler(self.status_bar_write)
  87. self.downloadHandler = None
  88. # init log manager
  89. self.logManager = None
  90. if self.optionsList.enableLog:
  91. self.logManager = LogManager(
  92. self.optionsList.get_config_path(),
  93. self.optionsList.writeTimeToLog
  94. )
  95. # init some thread variables
  96. self.downloadThread = None
  97. self.updateThread = None
  98. # init urlList for evt_text on self.trackList
  99. self.urlList = []
  100. # check & update libraries (youtube-dl)
  101. self.check_if_youtube_dl_exist()
  102. if (self.optionsList.autoUpdate):
  103. self.status_bar_write("Auto update enable")
  104. self.update_youtube_dl()
  105. def InitGUI(self):
  106. self.panel = wx.Panel(self)
  107. mainBoxSizer = wx.BoxSizer(wx.VERTICAL)
  108. urlTextBox = wx.BoxSizer(wx.HORIZONTAL)
  109. urlTextBox.Add(wx.StaticText(self.panel, label='URLs'), flag = wx.TOP, border=10)
  110. mainBoxSizer.Add(urlTextBox, flag = wx.LEFT, border=20)
  111. trckListBox = wx.BoxSizer(wx.HORIZONTAL)
  112. self.trackList = wx.TextCtrl(self.panel, size=(-1, 120), style = wx.TE_MULTILINE | wx.TE_DONTWRAP)
  113. trckListBox.Add(self.trackList, 1)
  114. mainBoxSizer.Add(trckListBox, flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border=20)
  115. buttonsBox = wx.BoxSizer(wx.HORIZONTAL)
  116. self.downloadButton = wx.Button(self.panel, label='Download', size=(90, 30))
  117. buttonsBox.Add(self.downloadButton)
  118. self.updateButton = wx.Button(self.panel, label='Update', size=(90, 30))
  119. buttonsBox.Add(self.updateButton, flag = wx.LEFT | wx.RIGHT, border=80)
  120. self.optionsButton = wx.Button(self.panel, label='Options', size=(90, 30))
  121. buttonsBox.Add(self.optionsButton)
  122. mainBoxSizer.Add(buttonsBox, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.BOTTOM | wx.TOP, border=10)
  123. stListBox = wx.BoxSizer(wx.HORIZONTAL)
  124. self.statusList = ListCtrl(self.panel, style = wx.LC_REPORT | wx.LC_HRULES | wx.LC_VRULES)
  125. stListBox.Add(self.statusList, 1, flag = wx.EXPAND)
  126. mainBoxSizer.Add(stListBox, 1, flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border=20)
  127. stBarBox = wx.BoxSizer(wx.HORIZONTAL)
  128. self.statusBar = wx.StaticText(self.panel, label='Author: Sotiris Papadopoulos')
  129. stBarBox.Add(self.statusBar, flag = wx.TOP | wx.BOTTOM, border=5)
  130. mainBoxSizer.Add(stBarBox, flag = wx.LEFT, border=20)
  131. self.panel.SetSizer(mainBoxSizer)
  132. def check_if_youtube_dl_exist(self):
  133. path = fix_path(self.optionsList.updatePath)+YOUTUBE_DL_FILENAME
  134. if not file_exist(path):
  135. self.status_bar_write("Youtube-dl is missing, trying to download it...")
  136. self.update_youtube_dl()
  137. def update_youtube_dl(self):
  138. self.downloadButton.Disable()
  139. self.updateThread = UpdateThread(self.optionsList.updatePath, YOUTUBE_DL_FILENAME)
  140. def status_bar_write(self, msg):
  141. self.statusBar.SetLabel(msg)
  142. def fin_task(self, msg):
  143. self.status_bar_write(msg)
  144. self.downloadButton.SetLabel('Download')
  145. self.updateButton.Enable()
  146. self.downloadThread.join()
  147. self.downloadThread = None
  148. self.downloadHandler = None
  149. self.urlList = []
  150. self.finished_popup()
  151. def download_handler(self, msg):
  152. self.downloadHandler.handle(msg)
  153. if self.downloadHandler._has_closed():
  154. self.status_bar_write('Stoping downloads')
  155. if self.downloadHandler._has_finished():
  156. if self.downloadHandler._has_error():
  157. if self.logManager != None:
  158. msg = 'An error occured while downloading. See Options>Log.'
  159. else:
  160. msg = 'An error occured while downloading'
  161. else:
  162. msg = 'Done'
  163. self.fin_task(msg)
  164. def update_handler(self, msg):
  165. if msg.data == 'finish':
  166. self.downloadButton.Enable()
  167. self.updateThread.join()
  168. self.updateThread = None
  169. else:
  170. self.status_bar_write(msg.data)
  171. def stop_download(self):
  172. self.downloadThread.close()
  173. def load_tracklist(self, trackList):
  174. for url in trackList:
  175. url = remove_spaces(url)
  176. if url != '':
  177. self.urlList.append(url)
  178. self.statusList._add_item(url)
  179. def start_download(self):
  180. self.statusList._clear_list()
  181. self.load_tracklist(self.trackList.GetValue().split('\n'))
  182. if not self.statusList._is_empty():
  183. options = YoutubeDLInterpreter(self.optionsList, YOUTUBE_DL_FILENAME).get_options()
  184. self.downloadThread = DownloadManager(
  185. options,
  186. self.statusList._get_items(),
  187. self.optionsList.clearDashFiles,
  188. self.logManager
  189. )
  190. self.downloadHandler = DownloadHandler(self.statusList)
  191. self.status_bar_write('Download started')
  192. self.downloadButton.SetLabel('Stop')
  193. self.updateButton.Disable()
  194. else:
  195. self.no_url_popup()
  196. def save_options(self):
  197. self.optionsList.save_to_file()
  198. def finished_popup(self):
  199. wx.MessageBox('Downloads completed.', 'Info', wx.OK | wx.ICON_INFORMATION)
  200. def no_url_popup(self):
  201. wx.MessageBox('You need to provide at least one url.', 'Error', wx.OK | wx.ICON_EXCLAMATION)
  202. def OnTrackListChange(self, event):
  203. if self.downloadThread != None:
  204. ''' Get current url list from trackList textCtrl '''
  205. curList = self.trackList.GetValue().split('\n')
  206. ''' For each url in current url list '''
  207. for url in curList:
  208. ''' Remove spaces from url '''
  209. url = remove_spaces(url)
  210. ''' If url is not in self.urlList (original downloads list) and url is not empty '''
  211. if url not in self.urlList and url != '':
  212. ''' Add url into original download list '''
  213. self.urlList.append(url)
  214. ''' Add handler for url '''
  215. self.downloadHandler._add_empty_handler()
  216. ''' Add url into statusList '''
  217. self.statusList._add_item(url)
  218. ''' Retrieve last item as {url:url, index:indexNo} '''
  219. item = self.statusList._get_last_item()
  220. ''' Pass that item into downloadThread '''
  221. self.downloadThread._add_download_item(item)
  222. def OnDownload(self, event):
  223. if self.downloadThread != None:
  224. self.stop_download()
  225. else:
  226. self.start_download()
  227. def OnUpdate(self, event):
  228. if (self.downloadThread == None and self.updateThread == None):
  229. self.update_youtube_dl()
  230. def OnOptions(self, event):
  231. optionsFrame = OptionsFrame(self.optionsList, parent=self, logger=self.logManager)
  232. optionsFrame.Show()
  233. def OnClose(self, event):
  234. self.save_options()
  235. self.Destroy()
  236. class ListCtrl(wx.ListCtrl, ListCtrlAutoWidthMixin):
  237. ''' Custom ListCtrl class '''
  238. def __init__(self, parent=None, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0):
  239. wx.ListCtrl.__init__(self, parent, id, pos, size, style)
  240. ListCtrlAutoWidthMixin.__init__(self)
  241. self.InsertColumn(0, 'Video', width=150)
  242. self.InsertColumn(1, 'Size', width=80)
  243. self.InsertColumn(2, 'Percent', width=65)
  244. self.InsertColumn(3, 'ETA', width=45)
  245. self.InsertColumn(4, 'Speed', width=90)
  246. self.InsertColumn(5, 'Status', width=160)
  247. self.setResizeColumn(0)
  248. self.ListIndex = 0
  249. ''' Add single item on list '''
  250. def _add_item(self, item):
  251. self.InsertStringItem(self.ListIndex, item)
  252. self.ListIndex += 1
  253. ''' Write data on index, column '''
  254. def _write_data(self, index, column, data):
  255. self.SetStringItem(index, column, data)
  256. ''' Clear list and set index to 0'''
  257. def _clear_list(self):
  258. self.DeleteAllItems()
  259. self.ListIndex = 0
  260. ''' Return True if list is empty '''
  261. def _is_empty(self):
  262. return self.ListIndex == 0
  263. ''' Get last item inserted, Returns dictionary '''
  264. def _get_last_item(self):
  265. data = {}
  266. last_item = self.GetItem(itemId=self.ListIndex-1, col=0)
  267. data['url'] = last_item.GetText()
  268. data['index'] = self.ListIndex-1
  269. return data
  270. ''' Retrieve all items [start, self.ListIndex), Returns list '''
  271. def _get_items(self, start=0):
  272. items = []
  273. for row in range(start, self.ListIndex):
  274. item = self.GetItem(itemId=row, col=0)
  275. data = {}
  276. data['url'] = item.GetText()
  277. data['index'] = row
  278. items.append(data)
  279. return items
  280. class LogPanel(wx.Panel):
  281. size = ''
  282. path = ''
  283. win_box_border = 0
  284. def __init__(self, parent, optList, log):
  285. wx.Panel.__init__(self, parent)
  286. self.SetBoxBorder()
  287. self.optList = optList
  288. self.log = log
  289. self.set_data()
  290. mainBoxSizer = wx.BoxSizer(wx.VERTICAL)
  291. enLogBox = wx.BoxSizer(wx.HORIZONTAL)
  292. self.enableLogChk = wx.CheckBox(self, label='Enable Log')
  293. enLogBox.Add(self.enableLogChk)
  294. mainBoxSizer.Add(enLogBox, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, border=20+self.win_box_border)
  295. wrTimeBox = wx.BoxSizer(wx.HORIZONTAL)
  296. self.enableTimeChk = wx.CheckBox(self, label='Write Time')
  297. wrTimeBox.Add(self.enableTimeChk)
  298. mainBoxSizer.Add(wrTimeBox, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, border=5+self.win_box_border)
  299. butBox = wx.BoxSizer(wx.HORIZONTAL)
  300. self.clearLogButton = wx.Button(self, label='Clear Log')
  301. butBox.Add(self.clearLogButton)
  302. self.viewLogButton = wx.Button(self, label='View Log')
  303. butBox.Add(self.viewLogButton, flag = wx.LEFT, border=20)
  304. mainBoxSizer.Add(butBox, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, border=15)
  305. if self.optList.enableLog:
  306. self.SetDataSizers(mainBoxSizer)
  307. self.SetSizer(mainBoxSizer)
  308. self.Bind(wx.EVT_CHECKBOX, self.OnEnable, self.enableLogChk)
  309. self.Bind(wx.EVT_CHECKBOX, self.OnTime, self.enableTimeChk)
  310. self.Bind(wx.EVT_BUTTON, self.OnClear, self.clearLogButton)
  311. self.Bind(wx.EVT_BUTTON, self.OnView, self.viewLogButton)
  312. def SetBoxBorder(self):
  313. ''' Set border for windows '''
  314. if get_os_type() == 'nt':
  315. self.win_box_border = 10
  316. def SetDataSizers(self, box):
  317. logPathText = wx.BoxSizer(wx.HORIZONTAL)
  318. logPathText.Add(wx.StaticText(self, label='Path: ' + self.path))
  319. box.Add(logPathText, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, border=20)
  320. logSizeText = wx.BoxSizer(wx.HORIZONTAL)
  321. self.sizeText = wx.StaticText(self, label='Log Size: ' + self.size)
  322. logSizeText.Add(self.sizeText)
  323. box.Add(logSizeText, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, border=10)
  324. def set_data(self):
  325. if self.log != None:
  326. self.size = str(self.log.size()) + ' Bytes'
  327. self.path = self.log.path
  328. def OnTime(self, event):
  329. if self.log != None:
  330. self.log.add_time = self.enableTimeChk.GetValue()
  331. def OnEnable(self, event):
  332. if self.enableLogChk.GetValue():
  333. self.enableTimeChk.Enable()
  334. else:
  335. self.enableTimeChk.Disable()
  336. self.restart_popup()
  337. def OnClear(self, event):
  338. if self.log != None:
  339. self.log.clear()
  340. self.sizeText.SetLabel('Log Size: 0 Bytes')
  341. def OnView(self, event):
  342. if self.log != None:
  343. log_gui = LogGUI(self.path, parent=self)
  344. log_gui.Show()
  345. def load_options(self):
  346. self.enableLogChk.SetValue(self.optList.enableLog)
  347. self.enableTimeChk.SetValue(self.optList.writeTimeToLog)
  348. if self.optList.enableLog == False:
  349. self.enableTimeChk.Disable()
  350. if self.log == None:
  351. self.clearLogButton.Disable()
  352. self.viewLogButton.Disable()
  353. def save_options(self):
  354. self.optList.enableLog = self.enableLogChk.GetValue()
  355. self.optList.writeTimeToLog = self.enableTimeChk.GetValue()
  356. def restart_popup(self):
  357. wx.MessageBox('Please restart ' + TITLE, 'Restart', wx.OK | wx.ICON_INFORMATION)
  358. class UpdatePanel(wx.Panel):
  359. def __init__(self, parent, optList):
  360. wx.Panel.__init__(self, parent)
  361. self.optList = optList
  362. mainBoxSizer = wx.BoxSizer(wx.VERTICAL)
  363. text = '''Enter the path where youtube-dlG should
  364. download the latest youtube-dl.'''
  365. helpText = wx.BoxSizer(wx.HORIZONTAL)
  366. helpText.Add(wx.StaticText(self, label=text), flag = wx.TOP, border=10)
  367. mainBoxSizer.Add(helpText, flag = wx.LEFT, border=80)
  368. pathText = wx.BoxSizer(wx.HORIZONTAL)
  369. pathText.Add(wx.StaticText(self, label='Path'), flag = wx.TOP, border=20)
  370. mainBoxSizer.Add(pathText, flag = wx.LEFT, border=95)
  371. upPathBox = wx.BoxSizer(wx.HORIZONTAL)
  372. self.updatePathBox = wx.TextCtrl(self)
  373. upPathBox.Add(self.updatePathBox, 1, flag = wx.TOP, border=5)
  374. mainBoxSizer.Add(upPathBox, flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border=90)
  375. autoUpBox = wx.BoxSizer(wx.HORIZONTAL)
  376. self.autoUpdateChk = wx.CheckBox(self, label='Auto Update youtube-dl')
  377. autoUpBox.Add(self.autoUpdateChk, flag = wx.TOP, border=30)
  378. mainBoxSizer.Add(autoUpBox, flag = wx.LEFT, border=100)
  379. self.SetSizer(mainBoxSizer)
  380. def load_options(self):
  381. self.updatePathBox.SetValue(self.optList.updatePath)
  382. self.autoUpdateChk.SetValue(self.optList.autoUpdate)
  383. def save_options(self):
  384. self.optList.updatePath = abs_path(self.updatePathBox.GetValue())
  385. self.optList.autoUpdate = self.autoUpdateChk.GetValue()
  386. class PlaylistPanel(wx.Panel):
  387. def __init__(self, parent, optList):
  388. wx.Panel.__init__(self, parent)
  389. self.optList = optList
  390. mainBoxSizer = wx.StaticBoxSizer(wx.StaticBox(self, label='Playlist Options'), wx.VERTICAL)
  391. mainBoxSizer.Add((-1, 10))
  392. startBox = wx.BoxSizer(wx.HORIZONTAL)
  393. startBox.Add(wx.StaticText(self, label='Start'), flag = wx.RIGHT, border=32)
  394. self.startSpnr = wx.SpinCtrl(self, size=(60, -1))
  395. self.startSpnr.SetRange(1, 999)
  396. startBox.Add(self.startSpnr)
  397. mainBoxSizer.Add(startBox, flag = wx.TOP | wx.LEFT, border=20)
  398. stopBox = wx.BoxSizer(wx.HORIZONTAL)
  399. stopBox.Add(wx.StaticText(self, label='Stop'), flag = wx.RIGHT, border=34)
  400. self.stopSpnr = wx.SpinCtrl(self, size=(60, -1))
  401. self.stopSpnr.SetRange(0, 999)
  402. stopBox.Add(self.stopSpnr)
  403. mainBoxSizer.Add(stopBox, flag = wx.TOP | wx.LEFT, border=20)
  404. maxBox = wx.BoxSizer(wx.HORIZONTAL)
  405. maxBox.Add(wx.StaticText(self, label='Max DLs'), flag = wx.RIGHT, border=self.get_border())
  406. self.maxSpnr = wx.SpinCtrl(self, size=(60, -1))
  407. self.maxSpnr.SetRange(0, 999)
  408. maxBox.Add(self.maxSpnr)
  409. mainBoxSizer.Add(maxBox, flag = wx.TOP | wx.LEFT, border=20)
  410. self.SetSizer(mainBoxSizer)
  411. def get_border(self):
  412. if get_os_type() == 'nt':
  413. return 16
  414. return 10
  415. def load_options(self):
  416. self.startSpnr.SetValue(self.optList.startTrack)
  417. self.stopSpnr.SetValue(self.optList.endTrack)
  418. self.maxSpnr.SetValue(self.optList.maxDownloads)
  419. def save_options(self):
  420. self.optList.startTrack = self.startSpnr.GetValue()
  421. self.optList.endTrack = self.stopSpnr.GetValue()
  422. self.optList.maxDownloads = self.maxSpnr.GetValue()
  423. class ConnectionPanel(wx.Panel):
  424. def __init__(self, parent, optList):
  425. wx.Panel.__init__(self, parent)
  426. self.optList = optList
  427. mainBoxSizer = wx.BoxSizer(wx.VERTICAL)
  428. retBox = wx.BoxSizer(wx.HORIZONTAL)
  429. retBox.Add(wx.StaticText(self, label='Retries'), flag = wx.RIGHT, border=8)
  430. self.retriesSpnr = wx.SpinCtrl(self, size=(50, -1))
  431. self.retriesSpnr.SetRange(1, 99)
  432. retBox.Add(self.retriesSpnr)
  433. mainBoxSizer.Add(retBox, flag = wx.LEFT | wx.TOP, border=10)
  434. uaText = wx.BoxSizer(wx.HORIZONTAL)
  435. uaText.Add(wx.StaticText(self, label='User Agent'), flag = wx.LEFT, border=15)
  436. mainBoxSizer.Add(uaText, flag = wx.TOP, border=10)
  437. mainBoxSizer.Add((-1, 5))
  438. uaBox = wx.BoxSizer(wx.HORIZONTAL)
  439. self.userAgentBox = wx.TextCtrl(self)
  440. uaBox.Add(self.userAgentBox, 1, flag = wx.LEFT, border=10)
  441. mainBoxSizer.Add(uaBox, flag = wx.EXPAND | wx.RIGHT, border=200)
  442. refText = wx.BoxSizer(wx.HORIZONTAL)
  443. refText.Add(wx.StaticText(self, label='Referer'), flag = wx.LEFT, border=15)
  444. mainBoxSizer.Add(refText, flag = wx.TOP, border=10)
  445. mainBoxSizer.Add((-1, 5))
  446. refBox = wx.BoxSizer(wx.HORIZONTAL)
  447. self.refererBox = wx.TextCtrl(self)
  448. refBox.Add(self.refererBox, 1, flag = wx.LEFT, border=10)
  449. mainBoxSizer.Add(refBox, flag = wx.EXPAND | wx.RIGHT, border=200)
  450. prxyText = wx.BoxSizer(wx.HORIZONTAL)
  451. prxyText.Add(wx.StaticText(self, label='Proxy'), flag = wx.LEFT, border=15)
  452. mainBoxSizer.Add(prxyText, flag = wx.TOP, border=10)
  453. mainBoxSizer.Add((-1, 5))
  454. prxyBox = wx.BoxSizer(wx.HORIZONTAL)
  455. self.proxyBox = wx.TextCtrl(self)
  456. prxyBox.Add(self.proxyBox, 1, flag = wx.LEFT, border=10)
  457. mainBoxSizer.Add(prxyBox, flag = wx.EXPAND | wx.RIGHT, border=100)
  458. self.SetSizer(mainBoxSizer)
  459. def load_options(self):
  460. self.userAgentBox.SetValue(self.optList.userAgent)
  461. self.refererBox.SetValue(self.optList.referer)
  462. self.proxyBox.SetValue(self.optList.proxy)
  463. self.retriesSpnr.SetValue(self.optList.retries)
  464. def save_options(self):
  465. self.optList.userAgent = self.userAgentBox.GetValue()
  466. self.optList.referer = self.refererBox.GetValue()
  467. self.optList.proxy = self.proxyBox.GetValue()
  468. self.optList.retries = self.retriesSpnr.GetValue()
  469. class AuthenticationPanel(wx.Panel):
  470. def __init__(self, parent, optList):
  471. wx.Panel.__init__(self,parent)
  472. self.optList = optList
  473. mainBoxSizer = wx.BoxSizer(wx.VERTICAL)
  474. usrTextBox = wx.BoxSizer(wx.HORIZONTAL)
  475. usrTextBox.Add(wx.StaticText(self, label='Username'))
  476. mainBoxSizer.Add(usrTextBox, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, border=15)
  477. usrBox = wx.BoxSizer(wx.HORIZONTAL)
  478. self.usernameBox = wx.TextCtrl(self, size=(-1, 25))
  479. usrBox.Add(self.usernameBox, 1, flag = wx.TOP, border=5)
  480. mainBoxSizer.Add(usrBox, flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border=160)
  481. passTextBox = wx.BoxSizer(wx.HORIZONTAL)
  482. passTextBox.Add(wx.StaticText(self, label='Password'))
  483. mainBoxSizer.Add(passTextBox, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, border=15)
  484. passBox = wx.BoxSizer(wx.HORIZONTAL)
  485. self.passwordBox = wx.TextCtrl(self, size=(-1, 25), style = wx.TE_PASSWORD)
  486. passBox.Add(self.passwordBox, 1, flag = wx.TOP, border=5)
  487. mainBoxSizer.Add(passBox, flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border=160)
  488. vPassTextBox = wx.BoxSizer(wx.HORIZONTAL)
  489. vPassTextBox.Add(wx.StaticText(self, label='Video Password (vimeo, smotri)'))
  490. mainBoxSizer.Add(vPassTextBox, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, border=15)
  491. vPassBox = wx.BoxSizer(wx.HORIZONTAL)
  492. self.videopassBox = wx.TextCtrl(self, size=(-1, 25), style = wx.TE_PASSWORD)
  493. vPassBox.Add(self.videopassBox, 1, flag = wx.TOP, border=5)
  494. mainBoxSizer.Add(vPassBox, flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border=160)
  495. self.SetSizer(mainBoxSizer)
  496. def load_options(self):
  497. self.usernameBox.SetValue(self.optList.username)
  498. self.passwordBox.SetValue(self.optList.password)
  499. self.videopassBox.SetValue(self.optList.videoPass)
  500. def save_options(self):
  501. self.optList.username = self.usernameBox.GetValue()
  502. self.optList.password = self.passwordBox.GetValue()
  503. self.optList.videoPass = self.videopassBox.GetValue()
  504. class AudioPanel(wx.Panel):
  505. win_box_border = 0
  506. def __init__(self, parent, optList):
  507. wx.Panel.__init__(self, parent)
  508. self.SetBoxBorder()
  509. self.optList = optList
  510. mainBoxSizer = wx.BoxSizer(wx.VERTICAL)
  511. toaBox = wx.BoxSizer(wx.HORIZONTAL)
  512. self.toAudioChk = wx.CheckBox(self, label='Convert to Audio')
  513. toaBox.Add(self.toAudioChk)
  514. mainBoxSizer.Add(toaBox, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, border=15+self.win_box_border)
  515. keepVBox = wx.BoxSizer(wx.HORIZONTAL)
  516. self.keepVideoChk = wx.CheckBox(self, label='Keep Video')
  517. keepVBox.Add(self.keepVideoChk)
  518. mainBoxSizer.Add(keepVBox, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, border=5+self.win_box_border)
  519. afTextBox = wx.BoxSizer(wx.HORIZONTAL)
  520. afTextBox.Add(wx.StaticText(self, label='Audio Format'))
  521. mainBoxSizer.Add(afTextBox, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, border=10)
  522. afComboBox = wx.BoxSizer(wx.HORIZONTAL)
  523. self.audioFormatCombo = wx.ComboBox(self, choices=AUDIOFORMATS, size=(160, 30))
  524. afComboBox.Add(self.audioFormatCombo)
  525. mainBoxSizer.Add(afComboBox, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, border=5)
  526. aqTextBox = wx.BoxSizer(wx.HORIZONTAL)
  527. aqTextBox.Add(wx.StaticText(self, label='Audio Quality 0 (best) 9 (worst)'))
  528. mainBoxSizer.Add(aqTextBox, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, border=10)
  529. aqComboBox = wx.BoxSizer(wx.HORIZONTAL)
  530. self.audioQualitySpnr = wx.SpinCtrl(self, size=(90, 20))
  531. self.audioQualitySpnr.SetRange(0, 9)
  532. aqComboBox.Add(self.audioQualitySpnr)
  533. mainBoxSizer.Add(aqComboBox, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, border=5)
  534. self.SetSizer(mainBoxSizer)
  535. self.Bind(wx.EVT_CHECKBOX, self.OnAudioCheck, self.toAudioChk)
  536. def SetBoxBorder(self):
  537. ''' Set border for windows '''
  538. if get_os_type() == 'nt':
  539. self.win_box_border = 5
  540. def OnAudioCheck(self, event):
  541. if self.toAudioChk.GetValue():
  542. self.keepVideoChk.Enable()
  543. self.audioFormatCombo.Enable()
  544. self.audioQualitySpnr.Enable()
  545. else:
  546. self.keepVideoChk.Disable()
  547. self.audioFormatCombo.Disable()
  548. self.audioQualitySpnr.Disable()
  549. def load_options(self):
  550. self.toAudioChk.SetValue(self.optList.toAudio)
  551. self.keepVideoChk.SetValue(self.optList.keepVideo)
  552. self.audioFormatCombo.SetValue(self.optList.audioFormat)
  553. self.audioQualitySpnr.SetValue(self.optList.audioQuality)
  554. if self.optList.toAudio == False:
  555. self.keepVideoChk.Disable()
  556. self.audioFormatCombo.Disable()
  557. self.audioQualitySpnr.Disable()
  558. def save_options(self):
  559. self.optList.toAudio = self.toAudioChk.GetValue()
  560. self.optList.keepVideo = self.keepVideoChk.GetValue()
  561. self.optList.audioFormat = self.audioFormatCombo.GetValue()
  562. self.optList.audioQuality = self.audioQualitySpnr.GetValue()
  563. class VideoPanel(wx.Panel):
  564. def __init__(self, parent, optList):
  565. wx.Panel.__init__(self, parent)
  566. self.optList = optList
  567. mainBoxSizer = wx.BoxSizer(wx.VERTICAL)
  568. vfTextBox = wx.BoxSizer(wx.HORIZONTAL)
  569. vfTextBox.Add(wx.StaticText(self, label='Video Format'))
  570. mainBoxSizer.Add(vfTextBox, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, border=20)
  571. vfComboBox = wx.BoxSizer(wx.HORIZONTAL)
  572. self.videoFormatCombo = wx.ComboBox(self, choices=VIDEOFORMATS, size=(160, 30))
  573. vfComboBox.Add(self.videoFormatCombo)
  574. mainBoxSizer.Add(vfComboBox, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, border=5)
  575. daTextBox = wx.BoxSizer(wx.HORIZONTAL)
  576. daTextBox.Add(wx.StaticText(self, label='DASH Audio'))
  577. mainBoxSizer.Add(daTextBox, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, border=10)
  578. daComboBox = wx.BoxSizer(wx.HORIZONTAL)
  579. self.dashAudioFormatCombo = wx.ComboBox(self, choices=DASH_AUDIO_FORMATS, size=(160, 30))
  580. daComboBox.Add(self.dashAudioFormatCombo)
  581. mainBoxSizer.Add(daComboBox, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, border=5)
  582. clrDashBox = wx.BoxSizer(wx.HORIZONTAL)
  583. self.clearDashFilesChk = wx.CheckBox(self, label='Clear DASH audio/video files')
  584. clrDashBox.Add(self.clearDashFilesChk)
  585. mainBoxSizer.Add(clrDashBox, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, border=20)
  586. self.SetSizer(mainBoxSizer)
  587. self.Bind(wx.EVT_COMBOBOX, self.OnVideoFormatPick, self.videoFormatCombo)
  588. self.Bind(wx.EVT_COMBOBOX, self.OnAudioFormatPick, self.dashAudioFormatCombo)
  589. def OnAudioFormatPick(self, event):
  590. if have_dash_audio(self.dashAudioFormatCombo.GetValue()):
  591. self.clearDashFilesChk.Enable()
  592. else:
  593. self.clearDashFilesChk.SetValue(False)
  594. self.clearDashFilesChk.Disable()
  595. def OnVideoFormatPick(self, event):
  596. if video_is_dash(self.videoFormatCombo.GetValue()):
  597. self.dashAudioFormatCombo.Enable()
  598. if have_dash_audio(self.dashAudioFormatCombo.GetValue()):
  599. self.clearDashFilesChk.Enable()
  600. else:
  601. self.clearDashFilesChk.SetValue(False)
  602. self.clearDashFilesChk.Disable()
  603. self.dashAudioFormatCombo.Disable()
  604. def load_options(self):
  605. self.videoFormatCombo.SetValue(self.optList.videoFormat)
  606. self.dashAudioFormatCombo.SetValue(self.optList.dashAudioFormat)
  607. self.clearDashFilesChk.SetValue(self.optList.clearDashFiles)
  608. if not video_is_dash(self.optList.videoFormat):
  609. self.dashAudioFormatCombo.Disable()
  610. if not have_dash_audio(self.optList.dashAudioFormat):
  611. self.clearDashFilesChk.SetValue(False)
  612. self.clearDashFilesChk.Disable()
  613. def save_options(self):
  614. self.optList.videoFormat = self.videoFormatCombo.GetValue()
  615. self.optList.dashAudioFormat = self.dashAudioFormatCombo.GetValue()
  616. self.optList.clearDashFiles = self.clearDashFilesChk.GetValue()
  617. class FilesystemPanel(wx.Panel):
  618. win_box_border = 0
  619. def __init__(self, parent, optList):
  620. wx.Panel.__init__(self, parent)
  621. self.SetBoxBorder()
  622. self.optList = optList
  623. mainBoxSizer = wx.BoxSizer(wx.HORIZONTAL)
  624. leftBoxSizer = wx.BoxSizer(wx.VERTICAL)
  625. rightBoxSizer = wx.StaticBoxSizer(wx.StaticBox(self, label='Filesize (e.g. 50k or 44.6m)'), wx.VERTICAL)
  626. self.SetLeftBox(leftBoxSizer)
  627. self.SetRightBox(rightBoxSizer)
  628. mainBoxSizer.Add(leftBoxSizer, 1, flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=10)
  629. mainBoxSizer.Add(rightBoxSizer, 1, flag = wx.EXPAND | wx.ALL | wx.ALIGN_CENTER, border=10)
  630. self.SetSizer(mainBoxSizer)
  631. def SetBoxBorder(self):
  632. ''' Set border for windows '''
  633. if get_os_type() == 'nt':
  634. self.win_box_border = 15
  635. def SetLeftBox(self, box):
  636. idBox = wx.BoxSizer(wx.HORIZONTAL)
  637. self.idAsNameChk = wx.CheckBox(self, label='ID as Name')
  638. idBox.Add(self.idAsNameChk, flag = wx.LEFT, border=5)
  639. box.Add(idBox, flag = wx.TOP, border=20)
  640. ignrBox = wx.BoxSizer(wx.HORIZONTAL)
  641. self.ignoreErrorsChk = wx.CheckBox(self, label='Ignore Errors')
  642. ignrBox.Add(self.ignoreErrorsChk, flag = wx.LEFT, border=5)
  643. box.Add(ignrBox, flag = wx.TOP, border=5+self.win_box_border)
  644. wrtDescBox = wx.BoxSizer(wx.HORIZONTAL)
  645. self.writeDescriptionChk = wx.CheckBox(self, label='Write description to file')
  646. wrtDescBox.Add(self.writeDescriptionChk, flag = wx.LEFT, border=5)
  647. box.Add(wrtDescBox, flag = wx.TOP, border=5+self.win_box_border)
  648. wrtInfoBox = wx.BoxSizer(wx.HORIZONTAL)
  649. self.writeInfoChk = wx.CheckBox(self, label='Write info to (.json) file')
  650. wrtInfoBox.Add(self.writeInfoChk, flag = wx.LEFT, border=5)
  651. box.Add(wrtInfoBox, flag = wx.TOP, border=5+self.win_box_border)
  652. wrtThumBox = wx.BoxSizer(wx.HORIZONTAL)
  653. self.writeThumbnailChk = wx.CheckBox(self, label='Write thumbnail to disk')
  654. wrtThumBox.Add(self.writeThumbnailChk, flag = wx.LEFT, border=5)
  655. box.Add(wrtThumBox, flag = wx.TOP, border=5+self.win_box_border)
  656. def SetRightBox(self, box):
  657. minBox = wx.BoxSizer(wx.HORIZONTAL)
  658. minBox.Add(wx.StaticText(self, label='Min'), flag = wx.RIGHT, border=12)
  659. self.minFilesizeBox = wx.TextCtrl(self, size=(80, -1))
  660. minBox.Add(self.minFilesizeBox)
  661. box.Add(minBox, flag = wx.TOP | wx.ALIGN_CENTER_HORIZONTAL, border=10)
  662. maxBox = wx.BoxSizer(wx.HORIZONTAL)
  663. maxBox.Add(wx.StaticText(self, label='Max'), flag = wx.RIGHT, border=8)
  664. self.maxFilesizeBox = wx.TextCtrl(self, size=(80, -1))
  665. maxBox.Add(self.maxFilesizeBox)
  666. box.Add(maxBox, flag = wx.TOP | wx.ALIGN_CENTER_HORIZONTAL, border=10)
  667. def load_options(self):
  668. self.writeDescriptionChk.SetValue(self.optList.writeDescription)
  669. self.writeInfoChk.SetValue(self.optList.writeInfo)
  670. self.writeThumbnailChk.SetValue(self.optList.writeThumbnail)
  671. self.ignoreErrorsChk.SetValue(self.optList.ignoreErrors)
  672. self.idAsNameChk.SetValue(self.optList.idAsName)
  673. self.minFilesizeBox.SetValue(self.optList.minFileSize)
  674. self.maxFilesizeBox.SetValue(self.optList.maxFileSize)
  675. def save_options(self):
  676. self.optList.writeDescription = self.writeDescriptionChk.GetValue()
  677. self.optList.writeInfo = self.writeInfoChk.GetValue()
  678. self.optList.writeThumbnail = self.writeThumbnailChk.GetValue()
  679. self.optList.ignoreErrors = self.ignoreErrorsChk.GetValue()
  680. self.optList.idAsName = self.idAsNameChk.GetValue()
  681. self.optList.minFileSize = self.minFilesizeBox.GetValue()
  682. self.optList.maxFileSize = self.maxFilesizeBox.GetValue()
  683. self.check_input()
  684. def check_input(self):
  685. self.optList.minFileSize.replace('-', '')
  686. self.optList.maxFileSize.replace('-', '')
  687. if self.optList.minFileSize == '':
  688. self.optList.minFileSize = '0'
  689. if self.optList.maxFileSize == '':
  690. self.optList.maxFileSize = '0'
  691. class SubtitlesPanel(wx.Panel):
  692. win_box_border = 0
  693. def __init__(self, parent, optList):
  694. wx.Panel.__init__(self, parent)
  695. self.SetBoxBorder()
  696. self.optList = optList
  697. mainBoxSizer = wx.BoxSizer(wx.VERTICAL)
  698. dlSubsBox = wx.BoxSizer(wx.HORIZONTAL)
  699. self.writeSubsChk = wx.CheckBox(self, label='Download subtitle file by language')
  700. dlSubsBox.Add(self.writeSubsChk, flag = wx.LEFT, border=10)
  701. mainBoxSizer.Add(dlSubsBox, flag = wx.TOP, border=15)
  702. dlAllSubBox = wx.BoxSizer(wx.HORIZONTAL)
  703. self.writeAllSubsChk = wx.CheckBox(self, label='Download all available subtitles')
  704. dlAllSubBox.Add(self.writeAllSubsChk, flag = wx.LEFT, border=10)
  705. mainBoxSizer.Add(dlAllSubBox, flag = wx.TOP, border=5+self.win_box_border)
  706. dlAutoSubBox = wx.BoxSizer(wx.HORIZONTAL)
  707. self.writeAutoSubsChk = wx.CheckBox(self, label='Download automatic subtitle file (YOUTUBE ONLY)')
  708. dlAutoSubBox.Add(self.writeAutoSubsChk, flag = wx.LEFT, border=10)
  709. mainBoxSizer.Add(dlAutoSubBox, flag = wx.TOP, border=5+self.win_box_border)
  710. embSubBox = wx.BoxSizer(wx.HORIZONTAL)
  711. self.embedSubsChk = wx.CheckBox(self, label='Embed subtitles in the video (only for mp4 videos)')
  712. self.embedSubsChk.Disable()
  713. embSubBox.Add(self.embedSubsChk, flag = wx.LEFT, border=10)
  714. mainBoxSizer.Add(embSubBox, flag = wx.TOP, border=5+self.win_box_border)
  715. slangTextBox = wx.BoxSizer(wx.HORIZONTAL)
  716. slangTextBox.Add(wx.StaticText(self, label='Subtitles Language'), flag = wx.LEFT, border=15)
  717. mainBoxSizer.Add(slangTextBox, flag = wx.TOP, border=10+self.win_box_border)
  718. slangBox = wx.BoxSizer(wx.HORIZONTAL)
  719. self.subsLangCombo = wx.ComboBox(self, choices=LANGUAGES, size=(140, 30))
  720. slangBox.Add(self.subsLangCombo, flag = wx.LEFT, border=10)
  721. mainBoxSizer.Add(slangBox, flag = wx.TOP, border=5)
  722. self.SetSizer(mainBoxSizer)
  723. self.Bind(wx.EVT_CHECKBOX, self.OnWriteSubsChk, self.writeSubsChk)
  724. self.Bind(wx.EVT_CHECKBOX, self.OnWriteAllSubsChk, self.writeAllSubsChk)
  725. self.Bind(wx.EVT_CHECKBOX, self.OnWriteAutoSubsChk, self.writeAutoSubsChk)
  726. def SetBoxBorder(self):
  727. ''' Set border for windows '''
  728. if get_os_type() == 'nt':
  729. self.win_box_border = 10
  730. def subs_are_on(self):
  731. return self.writeAutoSubsChk.GetValue() or self.writeSubsChk.GetValue()
  732. def OnWriteAutoSubsChk(self, event):
  733. if self.writeAutoSubsChk.GetValue():
  734. self.writeAllSubsChk.Disable()
  735. self.writeSubsChk.Disable()
  736. self.subsLangCombo.Disable()
  737. self.embedSubsChk.Enable()
  738. else:
  739. self.writeAllSubsChk.Enable()
  740. self.writeSubsChk.Enable()
  741. self.subsLangCombo.Enable()
  742. self.embedSubsChk.Disable()
  743. self.embedSubsChk.SetValue(False)
  744. def OnWriteSubsChk(self, event):
  745. if self.writeSubsChk.GetValue():
  746. self.writeAllSubsChk.Disable()
  747. self.writeAutoSubsChk.Disable()
  748. self.embedSubsChk.Enable()
  749. else:
  750. self.writeAllSubsChk.Enable()
  751. self.writeAutoSubsChk.Enable()
  752. self.embedSubsChk.Disable()
  753. self.embedSubsChk.SetValue(False)
  754. def OnWriteAllSubsChk(self, event):
  755. if self.writeAllSubsChk.GetValue():
  756. self.writeSubsChk.Disable()
  757. self.subsLangCombo.Disable()
  758. self.writeAutoSubsChk.Disable()
  759. else:
  760. self.writeSubsChk.Enable()
  761. self.subsLangCombo.Enable()
  762. self.writeAutoSubsChk.Enable()
  763. def load_options(self):
  764. self.writeSubsChk.Enable()
  765. self.subsLangCombo.Enable()
  766. self.writeAllSubsChk.Enable()
  767. self.writeAutoSubsChk.Enable()
  768. self.writeSubsChk.SetValue(self.optList.writeSubs)
  769. self.writeAllSubsChk.SetValue(self.optList.writeAllSubs)
  770. self.subsLangCombo.SetValue(self.optList.subsLang)
  771. self.writeAutoSubsChk.SetValue(self.optList.writeAutoSubs)
  772. self.embedSubsChk.SetValue(self.optList.embedSubs)
  773. if self.optList.writeSubs:
  774. self.writeAllSubsChk.Disable()
  775. self.writeAutoSubsChk.Disable()
  776. self.embedSubsChk.Enable()
  777. if self.optList.writeAllSubs:
  778. self.writeSubsChk.Disable()
  779. self.subsLangCombo.Disable()
  780. self.writeAutoSubsChk.Disable()
  781. if self.optList.writeAutoSubs:
  782. self.writeAllSubsChk.Disable()
  783. self.writeSubsChk.Disable()
  784. self.subsLangCombo.Disable()
  785. self.embedSubsChk.Enable()
  786. if not self.subs_are_on():
  787. self.embedSubsChk.Disable()
  788. def save_options(self):
  789. self.optList.writeSubs = self.writeSubsChk.GetValue()
  790. self.optList.writeAllSubs = self.writeAllSubsChk.GetValue()
  791. self.optList.subsLang = self.subsLangCombo.GetValue()
  792. self.optList.writeAutoSubs = self.writeAutoSubsChk.GetValue()
  793. self.optList.embedSubs = self.embedSubsChk.GetValue()
  794. class GeneralPanel(wx.Panel):
  795. def __init__(self, parent, optList, resetHandler):
  796. wx.Panel.__init__(self, parent)
  797. self.optList = optList
  798. self.resetHandler = resetHandler
  799. mainBoxSizer = wx.BoxSizer(wx.VERTICAL)
  800. svTextBox = wx.BoxSizer(wx.HORIZONTAL)
  801. svTextBox.Add(wx.StaticText(self, label='Save Path'))
  802. mainBoxSizer.Add(svTextBox, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.TOP, border=20)
  803. svPathBox = wx.BoxSizer(wx.HORIZONTAL)
  804. self.savePathBox = wx.TextCtrl(self)
  805. svPathBox.Add(self.savePathBox, 1, flag = wx.TOP, border=10)
  806. mainBoxSizer.Add(svPathBox, flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border=40)
  807. buttonsBox = wx.BoxSizer(wx.HORIZONTAL)
  808. self.aboutButton = wx.Button(self, label='About', size=(110, 40))
  809. buttonsBox.Add(self.aboutButton)
  810. self.openButton = wx.Button(self, label='Open', size=(110, 40))
  811. buttonsBox.Add(self.openButton, flag = wx.LEFT | wx.RIGHT, border=50)
  812. self.resetButton = wx.Button(self, label='Reset Options', size=(110, 40))
  813. buttonsBox.Add(self.resetButton)
  814. mainBoxSizer.Add(buttonsBox, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.BOTTOM | wx.TOP, border=20)
  815. setngsBox = wx.BoxSizer(wx.HORIZONTAL)
  816. text = 'Settings: ' + self.optList.settings_abs_path
  817. setngsBox.Add(wx.StaticText(self, label=text), flag = wx.TOP, border=20)
  818. mainBoxSizer.Add(setngsBox, flag = wx.ALIGN_CENTER_HORIZONTAL | wx.BOTTOM, border=10)
  819. self.SetSizer(mainBoxSizer)
  820. self.Bind(wx.EVT_BUTTON, self.OnAbout, self.aboutButton)
  821. self.Bind(wx.EVT_BUTTON, self.OnOpen, self.openButton)
  822. self.Bind(wx.EVT_BUTTON, self.OnReset, self.resetButton)
  823. def OnReset(self, event):
  824. self.resetHandler()
  825. def OnOpen(self, event):
  826. dlg = wx.DirDialog(None, "Choose directory")
  827. if dlg.ShowModal() == wx.ID_OK:
  828. self.savePathBox.SetValue(dlg.GetPath())
  829. dlg.Destroy()
  830. def OnAbout(self, event):
  831. description = '''A cross platform front-end GUI of
  832. the popular youtube-dl written in Python.'''
  833. license = '''This is free and unencumbered software released into the public domain.
  834. Anyone is free to copy, modify, publish, use, compile, sell, or
  835. distribute this software, either in source code form or as a compiled
  836. binary, for any purpose, commercial or non-commercial, and by any
  837. means.
  838. In jurisdictions that recognize copyright laws, the author or authors
  839. of this software dedicate any and all copyright interest in the
  840. software to the public domain. We make this dedication for the benefit
  841. of the public at large and to the detriment of our heirs and
  842. successors. We intend this dedication to be an overt act of
  843. relinquishment in perpetuity of all present and future rights to this
  844. software under copyright law.
  845. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  846. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  847. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  848. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  849. OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  850. ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  851. OTHER DEALINGS IN THE SOFTWARE.
  852. For more information, please refer to <http://unlicense.org/>'''
  853. info = wx.AboutDialogInfo()
  854. info.SetIcon(wx.Icon(ICON, wx.BITMAP_TYPE_ICO))
  855. info.SetName(TITLE)
  856. info.SetVersion(__version__)
  857. info.SetDescription(description)
  858. info.SetWebSite('http://mrs0m30n3.github.io/youtube-dl-gui/')
  859. info.SetLicense(license)
  860. info.AddDeveloper('Sotiris Papadopoulos')
  861. wx.AboutBox(info)
  862. def load_options(self):
  863. self.savePathBox.SetValue(self.optList.savePath)
  864. def save_options(self):
  865. self.optList.savePath = abs_path(self.savePathBox.GetValue())
  866. class OtherPanel(wx.Panel):
  867. def __init__(self, parent, optList):
  868. wx.Panel.__init__(self, parent)
  869. self.optList = optList
  870. mainBoxSizer = wx.BoxSizer(wx.VERTICAL)
  871. textBox = wx.BoxSizer(wx.HORIZONTAL)
  872. textBox.Add(wx.StaticText(self, label='Command line arguments (e.g. --help)'), flag = wx.TOP, border=30)
  873. mainBoxSizer.Add(textBox, flag = wx.LEFT, border=50)
  874. inputBox = wx.BoxSizer(wx.HORIZONTAL)
  875. self.cmdArgsBox = wx.TextCtrl(self)
  876. inputBox.Add(self.cmdArgsBox, 1, flag = wx.TOP, border=10)
  877. mainBoxSizer.Add(inputBox, flag = wx.EXPAND | wx.LEFT | wx.RIGHT, border=50)
  878. self.SetSizer(mainBoxSizer)
  879. def load_options(self):
  880. self.cmdArgsBox.SetValue(self.optList.cmdArgs)
  881. def save_options(self):
  882. self.optList.cmdArgs = self.cmdArgsBox.GetValue()
  883. class OptionsFrame(wx.Frame):
  884. def __init__(self, optionsList, parent=None, id=-1, logger=None):
  885. wx.Frame.__init__(self, parent, id, "Options", size=(580, 250))
  886. self.optionsList = optionsList
  887. panel = wx.Panel(self)
  888. notebook = wx.Notebook(panel)
  889. self.generalTab = GeneralPanel(notebook, self.optionsList, self.reset)
  890. self.audioTab = AudioPanel(notebook, self.optionsList)
  891. self.connectionTab = ConnectionPanel(notebook, self.optionsList)
  892. self.videoTab = VideoPanel(notebook, self.optionsList)
  893. self.filesysTab = FilesystemPanel(notebook, self.optionsList)
  894. self.subtitlesTab = SubtitlesPanel(notebook, self.optionsList)
  895. self.otherTab = OtherPanel(notebook, self.optionsList)
  896. self.updateTab = UpdatePanel(notebook, self.optionsList)
  897. self.authTab = AuthenticationPanel(notebook, self.optionsList)
  898. self.videoselTab = PlaylistPanel(notebook, self.optionsList)
  899. self.logTab = LogPanel(notebook, self.optionsList, logger)
  900. notebook.AddPage(self.generalTab, "General")
  901. notebook.AddPage(self.videoTab, "Video")
  902. notebook.AddPage(self.audioTab, "Audio")
  903. notebook.AddPage(self.videoselTab, "Playlist")
  904. notebook.AddPage(self.subtitlesTab, "Subtitles")
  905. notebook.AddPage(self.filesysTab, "Filesystem")
  906. notebook.AddPage(self.connectionTab, "Connection")
  907. notebook.AddPage(self.authTab, "Authentication")
  908. notebook.AddPage(self.updateTab, "Update")
  909. notebook.AddPage(self.logTab, "Log")
  910. notebook.AddPage(self.otherTab, "Commands")
  911. sizer = wx.BoxSizer()
  912. sizer.Add(notebook, 1, wx.EXPAND)
  913. panel.SetSizer(sizer)
  914. self.Bind(wx.EVT_CLOSE, self.OnClose)
  915. self.load_all_options()
  916. def OnClose(self, event):
  917. self.save_all_options()
  918. if not file_exist(fix_path(self.optionsList.updatePath)+YOUTUBE_DL_FILENAME):
  919. self.wrong_youtubedl_path()
  920. self.Destroy()
  921. def wrong_youtubedl_path(self):
  922. text = '''The path under Options>Update is invalid
  923. please do one of the following:
  924. *) restart youtube-dlG
  925. *) click the update button
  926. *) change the path to point where youtube-dl is'''
  927. wx.MessageBox(text, 'Error', wx.OK | wx.ICON_EXCLAMATION)
  928. def reset(self):
  929. self.optionsList.load_default()
  930. self.load_all_options()
  931. def load_all_options(self):
  932. self.generalTab.load_options()
  933. self.audioTab.load_options()
  934. self.connectionTab.load_options()
  935. self.videoTab.load_options()
  936. self.filesysTab.load_options()
  937. self.subtitlesTab.load_options()
  938. self.otherTab.load_options()
  939. self.updateTab.load_options()
  940. self.authTab.load_options()
  941. self.videoselTab.load_options()
  942. self.logTab.load_options()
  943. def save_all_options(self):
  944. self.generalTab.save_options()
  945. self.audioTab.save_options()
  946. self.connectionTab.save_options()
  947. self.videoTab.save_options()
  948. self.filesysTab.save_options()
  949. self.subtitlesTab.save_options()
  950. self.otherTab.save_options()
  951. self.updateTab.save_options()
  952. self.authTab.save_options()
  953. self.videoselTab.save_options()
  954. self.logTab.save_options()