diff --git a/youtube_dl_gui/DownloadThread.py b/youtube_dl_gui/DownloadThread.py index 0a7f97e..7468efb 100644 --- a/youtube_dl_gui/DownloadThread.py +++ b/youtube_dl_gui/DownloadThread.py @@ -22,10 +22,11 @@ PUBLISHER_TOPIC = 'download' class DownloadManager(Thread): - def __init__(self, options, downloadlist, clear_dash_files): + def __init__(self, options, downloadlist, clear_dash_files, logmanager=None): super(DownloadManager, self).__init__() self.clear_dash_files = clear_dash_files self.downloadlist = downloadlist + self.logmanager = logmanager self.options = options self.running = True self.procList = [] @@ -50,7 +51,8 @@ class DownloadManager(Thread): self.options, url, index, - self.clear_dash_files + self.clear_dash_files, + self.logmanager ) ) self.procNo += 1 @@ -101,11 +103,12 @@ class DownloadManager(Thread): class ProcessWrapper(Thread): - def __init__(self, options, url, index, clear_dash_files): + def __init__(self, options, url, index, clear_dash_files, log=None): super(ProcessWrapper, self).__init__() self.clear_dash_files = clear_dash_files self.options = options self.index = index + self.log = log self.url = url self.filenames = [] self.proc = None @@ -123,17 +126,22 @@ class ProcessWrapper(Thread): # read output output = self.read() if output != '': - # process output - data = self.proc_output(output) if self.err: + self.write_to_log(output) CallAfter(Publisher.sendMessage, PUBLISHER_TOPIC, ['error', self.index]) else: + # process output + data = self.proc_output(output) CallAfter(Publisher.sendMessage, PUBLISHER_TOPIC, data) if not self.err and not self.stopped: if self.clear_dash_files: self.cleardash() CallAfter(Publisher.sendMessage, PUBLISHER_TOPIC, ['finish', self.index]) - + + def write_to_log(self, data): + if self.log != None: + self.log.write(data) + def extract_filename(self, data): data_list = data.split(':') if 'Destination' in data_list[0].split(): diff --git a/youtube_dl_gui/LogManager.py b/youtube_dl_gui/LogManager.py new file mode 100644 index 0000000..88f9f0b --- /dev/null +++ b/youtube_dl_gui/LogManager.py @@ -0,0 +1,60 @@ +#! /usr/bin/env python + +import wx + +from time import strftime +from .Utils import ( + fix_path, + file_exist, + get_filesize +) + +LOG_FILENAME = 'log' +LOG_FILESIZE = 524288 # 524288B = 512kB + +class LogManager(): + + def __init__(self, path, add_time=False): + self.path = fix_path(path) + LOG_FILENAME + self.add_time = add_time + self.init_log() + self.check_log() + + def check_log(self): + if self.log_size() > LOG_FILESIZE: + self.clear() + + def init_log(self): + if not file_exist(self.path): + self.clear() + + def log_size(self): + return get_filesize(self.path) + + def clear(self): + with open(self.path, 'w') as fl: + fl.write('') + + def write(self, data): + with open(self.path, 'a') as fl: + if self.add_time: + t = '[%s] ' % strftime('%c') + fl.write(t) + fl.write(data) + fl.write('\n') + +class LogGUI(wx.Frame): + + title = 'Log Viewer' + + def __init__(self, path, parent=None, id=-1): + wx.Frame.__init__(self, parent, id, self.title, size=(650, 200)) + + panel = wx.Panel(self) + textArea = wx.TextCtrl(panel, -1, style = wx.TE_MULTILINE | wx.TE_READONLY | wx.HSCROLL) + sizer = wx.BoxSizer() + sizer.Add(textArea, 1, wx.EXPAND) + panel.SetSizerAndFit(sizer) + + textArea.LoadFile(path) + diff --git a/youtube_dl_gui/OptionsHandler.py b/youtube_dl_gui/OptionsHandler.py index db2bcde..019b85b 100644 --- a/youtube_dl_gui/OptionsHandler.py +++ b/youtube_dl_gui/OptionsHandler.py @@ -63,6 +63,8 @@ class OptionsHandler(): self.updatePath = self.get_config_path() self.autoUpdate = False self.cmdArgs = "" + self.enableLog = True + self.writeTimeToLog = True def get_config_path(self): if get_os_type() == 'nt': @@ -133,6 +135,8 @@ class OptionsHandler(): self.updatePath = opts[28].decode('utf8') self.autoUpdate = opts[29] in ['True'] self.cmdArgs = opts[30] + self.enableLog = opts[31] in ['True'] + self.writeTimeToLog = opts[32] in ['True'] except: self.statusBarWrite('Error while loading settings file') self.load_default() @@ -175,5 +179,7 @@ class OptionsHandler(): f.write('UpdatePath='+self.updatePath.encode('utf-8')+'\n') f.write('AutoUpdate='+str(self.autoUpdate)+'\n') f.write('CmdArgs='+str(self.cmdArgs)+'\n') + f.write('EnableLog='+str(self.enableLog)+'\n') + f.write('WriteTimeToLog='+str(self.writeTimeToLog)+'\n') f.close() diff --git a/youtube_dl_gui/SignalHandler.py b/youtube_dl_gui/SignalHandler.py index 23b4c4f..7bbef47 100644 --- a/youtube_dl_gui/SignalHandler.py +++ b/youtube_dl_gui/SignalHandler.py @@ -6,6 +6,7 @@ class DownloadHandler(): self.ListCtrl = ListCtrl self.finished = False self.close = False + self.error = False self.handlers = [] def _has_closed(self): @@ -13,11 +14,15 @@ class DownloadHandler(): def _has_finished(self): return self.finished + + def _has_error(self): + return self.error def handle(self, msg): ''' Handles msg base to Signals.txt ''' data = msg.data index = self.get_index(data) + self.check_for_error(data) if index == -1: if data[0] == 'finish': self.finished = True @@ -33,7 +38,11 @@ class DownloadHandler(): def get_index(self, data): return data.pop() - + + def check_for_error(self, data): + if data[0] == 'error': + self.error = True + class IndexDownloadHandler(): def __init__(self, ListCtrl, index): diff --git a/youtube_dl_gui/Utils.py b/youtube_dl_gui/Utils.py index 8f13015..58aa488 100644 --- a/youtube_dl_gui/Utils.py +++ b/youtube_dl_gui/Utils.py @@ -63,7 +63,10 @@ def file_exist(filename): def get_os_type(): return os.name - + +def get_filesize(path): + return os.path.getsize(path) + def makedir(path): os.makedirs(path) diff --git a/youtube_dl_gui/YoutubeDLGUI.py b/youtube_dl_gui/YoutubeDLGUI.py index 5d140bd..3908f94 100644 --- a/youtube_dl_gui/YoutubeDLGUI.py +++ b/youtube_dl_gui/YoutubeDLGUI.py @@ -27,6 +27,7 @@ from .DownloadThread import DownloadManager from .OptionsHandler import OptionsHandler from .YoutubeDLInterpreter import YoutubeDLInterpreter from .SignalHandler import DownloadHandler +from .LogManager import LogManager, LogGUI from .Utils import ( video_is_dash, have_dash_audio, @@ -110,6 +111,13 @@ class MainFrame(wx.Frame): self.optionsList = OptionsHandler(self.status_bar_write) self.downloadHandler = None + # init log manager + if self.optionsList.enableLog: + self.logManager = LogManager( + self.optionsList.get_config_path(), + self.optionsList.writeTimeToLog + ) + # init some thread variables self.downloadThread = None self.updateThread = None @@ -145,8 +153,12 @@ class MainFrame(wx.Frame): def status_bar_write(self, msg): self.statusBar.SetLabel(msg) - def fin_task(self): - self.status_bar_write('Done') + def fin_task(self, error): + if error: + msg = 'An error occured while downloading. See Options>Log.' + self.status_bar_write(msg) + else: + self.status_bar_write('Done') self.downloadButton.SetLabel('Download') self.updateButton.Enable() self.downloadThread.join() @@ -160,7 +172,7 @@ class MainFrame(wx.Frame): if self.downloadHandler._has_closed(): self.status_bar_write('Stoping downloads') if self.downloadHandler._has_finished(): - self.fin_task() + self.fin_task(self.downloadHandler._has_error()) def update_handler(self, msg): if msg.data == 'finish': @@ -185,7 +197,8 @@ class MainFrame(wx.Frame): self.downloadThread = DownloadManager( options, self.statusList._get_items(), - self.optionsList.clearDashFiles + self.optionsList.clearDashFiles, + self.logManager ) self.downloadHandler = DownloadHandler(self.statusList) self.downloadButton.SetLabel('Stop') @@ -231,7 +244,7 @@ class MainFrame(wx.Frame): self.update_youtube_dl() def OnOptions(self, event): - optionsFrame = OptionsFrame(self.optionsList, self) + optionsFrame = OptionsFrame(self.optionsList, self, logger=self.logManager) optionsFrame.Show() def OnClose(self, event): @@ -288,6 +301,72 @@ class ListCtrl(wx.ListCtrl): items.append(data) return items +class LogPanel(wx.Panel): + + def __init__(self, parent, optList, log): + self.optList = optList + self.log = log + self.size, self.path = self.set_data() + + wx.Panel.__init__(self, parent) + self.enableLogChk = wx.CheckBox(self, -1, 'Enable log', (240, 20)) + self.enableTimeChk = wx.CheckBox(self, -1, 'Write time', (240, 50)) + self.clearLogButton = wx.Button(self, label="Clear Log", pos=(200, 90)) + self.viewLogButton = wx.Button(self, label="View Log", pos=(300, 90)) + wx.StaticText(self, -1, 'Path: ' + self.path, (180, 140)) + self.sizeText = wx.StaticText(self, -1, 'Log Size: ' + self.size, (230, 170)) + + self.Bind(wx.EVT_CHECKBOX, self.OnEnable, self.enableLogChk) + self.Bind(wx.EVT_CHECKBOX, self.OnTime, self.enableTimeChk) + self.Bind(wx.EVT_BUTTON, self.OnClear, self.clearLogButton) + self.Bind(wx.EVT_BUTTON, self.OnView, self.viewLogButton) + + def set_data(self): + if self.log != None: + size = str(self.log.log_size()) + ' Bytes' + path = self.log.path + else: + size = '' + path = '' + return size, path + + def OnTime(self, event): + if self.log != None: + self.log.add_time = self.enableTimeChk.GetValue() + + def OnEnable(self, event): + if self.enableLogChk.GetValue(): + self.enableTimeChk.Enable() + else: + self.enableTimeChk.Disable() + self.restart_popup() + + def OnClear(self, event): + if self.log != None: + self.log.clear() + self.sizeText.SetLabel('Log Size: 0 Bytes') + + def OnView(self, event): + if self.log != None: + log_gui = LogGUI(self.path, parent=self) + log_gui.Show() + + def load_options(self): + self.enableLogChk.SetValue(self.optList.enableLog) + self.enableTimeChk.SetValue(self.optList.writeTimeToLog) + if self.optList.enableLog == False: + self.enableTimeChk.Disable() + if self.log == None: + self.clearLogButton.Disable() + self.viewLogButton.Disable() + + def save_options(self): + self.optList.enableLog = self.enableLogChk.GetValue() + self.optList.writeTimeToLog = self.enableTimeChk.GetValue() + + def restart_popup(self): + wx.MessageBox('Please restart ' + TITLE, 'Restart', wx.OK | wx.ICON_INFORMATION) + class UpdatePanel(wx.Panel): def __init__(self, parent, optList): @@ -686,7 +765,7 @@ class OtherPanel(wx.Panel): class OptionsFrame(wx.Frame): - def __init__(self, optionsList, parent=None, id=-1): + def __init__(self, optionsList, parent=None, id=-1, logger=None): wx.Frame.__init__(self, parent, id, "Options", size=(580, 250)) self.optionsList = optionsList @@ -704,6 +783,7 @@ class OptionsFrame(wx.Frame): self.updateTab = UpdatePanel(notebook, self.optionsList) self.authTab = AuthenticationPanel(notebook, self.optionsList) self.videoselTab = PlaylistPanel(notebook, self.optionsList) + self.logTab = LogPanel(notebook, self.optionsList, logger) notebook.AddPage(self.generalTab, "General") notebook.AddPage(self.videoTab, "Video") @@ -714,6 +794,7 @@ class OptionsFrame(wx.Frame): notebook.AddPage(self.connectionTab, "Connection") notebook.AddPage(self.authTab, "Authentication") notebook.AddPage(self.updateTab, "Update") + notebook.AddPage(self.logTab, "Log") notebook.AddPage(self.otherTab, "Commands") sizer = wx.BoxSizer() @@ -753,6 +834,7 @@ please do one of the following: self.updateTab.load_options() self.authTab.load_options() self.videoselTab.load_options() + self.logTab.load_options() def save_all_options(self): self.generalTab.save_options() @@ -765,4 +847,5 @@ please do one of the following: self.updateTab.save_options() self.authTab.save_options() self.videoselTab.save_options() + self.logTab.save_options() diff --git a/youtube_dl_gui/version.py b/youtube_dl_gui/version.py index e1424ed..73e3bb4 100644 --- a/youtube_dl_gui/version.py +++ b/youtube_dl_gui/version.py @@ -1 +1 @@ -__version__ = '0.3.1' +__version__ = '0.3.2'