fixed playlist output
This commit is contained in:
parent
0af9b3829b
commit
d1d4f68e71
20
SIGNALS.txt
20
SIGNALS.txt
@ -4,9 +4,13 @@ Signals list, that DownloadManager thread sends (DownloadThread.py)
|
||||
HANDLER
|
||||
=======
|
||||
|
||||
YoutubeDLGUI.py
|
||||
def download_handler(self, msg):
|
||||
...
|
||||
SignalHandler.py
|
||||
|
||||
class DownloadHandler()
|
||||
def handle(self, msg):
|
||||
.
|
||||
.
|
||||
.
|
||||
|
||||
SIGNALS
|
||||
=======
|
||||
@ -21,13 +25,15 @@ SIGNALS
|
||||
|
||||
['error', index]: Error occured url, index
|
||||
|
||||
['[youtube]', ..., index]: Pre-Processing for url, index
|
||||
['playlist', data, index]: Playlist data for url, index
|
||||
|
||||
['[download]', ..., index]: Downloading url, index
|
||||
['[youtube]', index]: Pre-Processing for url, index
|
||||
|
||||
['[ffmpeg]', ..., index]: Post-Processing for url, index
|
||||
['[download]', data, index]: Downloading url, index
|
||||
|
||||
['ignore'] Do nothing
|
||||
['[ffmpeg]', index]: Post-Processing for url, index
|
||||
|
||||
['ignore', index] Do nothing
|
||||
|
||||
EXAMPLES
|
||||
========
|
||||
|
3
setup.py
3
setup.py
@ -1,9 +1,10 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
from distutils.core import setup
|
||||
from youtube_dl_gui import version
|
||||
|
||||
setup(name='Youtube-DLG',
|
||||
version='0.2',
|
||||
version=version.__version__,
|
||||
description='Youtube-dl GUI',
|
||||
author='Sotiris Papadopoulos',
|
||||
author_email='ytubedlg@gmail.com',
|
||||
|
@ -9,6 +9,13 @@ from threading import Thread
|
||||
from wx.lib.pubsub import setuparg1
|
||||
from wx.lib.pubsub import pub as Publisher
|
||||
|
||||
from .Utils import (
|
||||
remove_spaces,
|
||||
string_to_array,
|
||||
get_encoding,
|
||||
encode_list
|
||||
)
|
||||
|
||||
OS_TYPE = name
|
||||
MAX_DOWNLOAD_THREADS = 3
|
||||
PUBLISHER_TOPIC = 'download'
|
||||
@ -73,17 +80,16 @@ class DownloadManager(Thread):
|
||||
|
||||
def check_queue(self, t=1):
|
||||
for proc in self.procList:
|
||||
if not self.running:
|
||||
break
|
||||
if not self.running: break
|
||||
if not proc.isAlive():
|
||||
return proc
|
||||
sleep(t)
|
||||
return None
|
||||
|
||||
def close(self):
|
||||
CallAfter(Publisher.sendMessage, PUBLISHER_TOPIC, ['close', -1])
|
||||
self.running = False
|
||||
self.procNo = 0
|
||||
self.running = False
|
||||
CallAfter(Publisher.sendMessage, PUBLISHER_TOPIC, ['close', -1])
|
||||
|
||||
class ProcessWrapper(Thread):
|
||||
|
||||
@ -93,21 +99,22 @@ class ProcessWrapper(Thread):
|
||||
self.index = index
|
||||
self.url = url
|
||||
self.proc = None
|
||||
self.info = None
|
||||
self.err = False
|
||||
self.stopped = False
|
||||
self.set_process_info()
|
||||
self.err = False
|
||||
self.start()
|
||||
|
||||
def run(self):
|
||||
self.proc = subprocess.Popen(self.get_cmd(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, startupinfo=self.info)
|
||||
self.proc = subprocess.Popen(self.get_cmd(),
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
startupinfo=self.set_process_info())
|
||||
# while subprocess is alive and NOT the current thread
|
||||
while self.proc_is_alive():
|
||||
# read output
|
||||
output = self.read()
|
||||
if output != '':
|
||||
# process output
|
||||
data = self.proc_output(output)
|
||||
data = self.check_data(data)
|
||||
if self.err:
|
||||
CallAfter(Publisher.sendMessage, PUBLISHER_TOPIC, ['error', self.index])
|
||||
else:
|
||||
@ -117,8 +124,8 @@ class ProcessWrapper(Thread):
|
||||
|
||||
def close(self):
|
||||
self.proc.kill()
|
||||
CallAfter(Publisher.sendMessage, PUBLISHER_TOPIC, ['close', self.index])
|
||||
self.stopped = True
|
||||
CallAfter(Publisher.sendMessage, PUBLISHER_TOPIC, ['close', self.index])
|
||||
|
||||
def proc_is_alive(self):
|
||||
return self.proc.poll() == None
|
||||
@ -132,41 +139,40 @@ class ProcessWrapper(Thread):
|
||||
return output.rstrip()
|
||||
|
||||
def proc_output(self, output):
|
||||
data = self.remove_spaces(self.string_to_array(output))
|
||||
data = remove_spaces(string_to_array(output))
|
||||
data.append(self.index)
|
||||
data = self.filter_data(data)
|
||||
return data
|
||||
|
||||
def check_data(self, data):
|
||||
''' check data for exceptions '''
|
||||
def filter_data(self, data):
|
||||
''' Filters data for output exceptions '''
|
||||
filter_list = ['Destination:', '100%', 'Resuming']
|
||||
if len(data) > 3:
|
||||
if data[1] == "UnicodeWarning:":
|
||||
self.err = False
|
||||
return ['ignore']
|
||||
if data[0] == "[download]" and data[1] == "Destination:":
|
||||
return ['ignore']
|
||||
if data[0] == "[download]" and data[1] == "100%":
|
||||
return ['ignore']
|
||||
if data[0] == "[download]" and len(data[1]) > 10:
|
||||
return ['ignore']
|
||||
if data[0] == "[download]" and data[1] == "Resuming":
|
||||
return ['ignore']
|
||||
if data[0] == '[download]':
|
||||
if data[1] in filter_list or len(data[1]) > 11:
|
||||
return ['ignore', self.index]
|
||||
if data[1] == 'Downloading':
|
||||
if data[2] == 'video':
|
||||
return ['playlist', data[3], data[5], self.index]
|
||||
else:
|
||||
return ['ignore', self.index]
|
||||
else:
|
||||
if data[1] == 'UnicodeWarning:':
|
||||
self.err = False
|
||||
return ['ignore', self.index]
|
||||
return data
|
||||
|
||||
def get_cmd(self):
|
||||
data = self.options + [self.url]
|
||||
if OS_TYPE == 'nt':
|
||||
enc = sys.getfilesystemencoding()
|
||||
data = [x.encode(enc, 'ignore') for x in data]
|
||||
return data
|
||||
enc = get_encoding()
|
||||
if enc != None:
|
||||
data = encode_list(self.options + [self.url], enc)
|
||||
return self.options + [self.url]
|
||||
|
||||
def string_to_array(self, string):
|
||||
return string.split(' ')
|
||||
|
||||
def remove_spaces(self, array):
|
||||
return [x for x in array if x != '']
|
||||
|
||||
def set_process_info(self):
|
||||
if OS_TYPE == 'nt':
|
||||
self.info = subprocess.STARTUPINFO()
|
||||
self.info.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
||||
info = subprocess.STARTUPINFO()
|
||||
info.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
||||
return info
|
||||
else:
|
||||
return None
|
||||
|
95
youtube_dl_gui/SignalHandler.py
Normal file
95
youtube_dl_gui/SignalHandler.py
Normal file
@ -0,0 +1,95 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
class DownloadHandler():
|
||||
|
||||
def __init__(self, ListCtrl):
|
||||
self.ListCtrl = ListCtrl
|
||||
self.finished = False
|
||||
self.close = False
|
||||
self.handlers = []
|
||||
|
||||
def _has_closed(self):
|
||||
return self.close
|
||||
|
||||
def _has_finished(self):
|
||||
return self.finished
|
||||
|
||||
def handle(self, msg):
|
||||
''' Handles msg base to Signals.txt '''
|
||||
data = msg.data
|
||||
index = self.get_index(data)
|
||||
if index == -1:
|
||||
if data[0] == 'finish':
|
||||
self.finished = True
|
||||
elif data[0] == 'close':
|
||||
self.close = True
|
||||
else:
|
||||
''' Manage handlers for its index '''
|
||||
if index == len(self.handlers):
|
||||
''' Create new IndexDownloadHandler and add it to handlers '''
|
||||
self.handlers.append(IndexDownloadHandler(self.ListCtrl, index))
|
||||
''' Let IndexDownloadHandler handle message data for current index '''
|
||||
self.handlers[index].handle(data)
|
||||
|
||||
def get_index(self, data):
|
||||
return data.pop()
|
||||
|
||||
class IndexDownloadHandler():
|
||||
|
||||
def __init__(self, ListCtrl, index):
|
||||
self.ListCtrl = ListCtrl
|
||||
self.index = index
|
||||
self.info = ''
|
||||
|
||||
def handle(self, data):
|
||||
''' Handle its data message for current index '''
|
||||
if data[0] == 'finish':
|
||||
self.finish()
|
||||
elif data[0] == 'close':
|
||||
self.close()
|
||||
elif data[0] == 'error':
|
||||
self.error()
|
||||
elif data[0] == 'playlist':
|
||||
self.playlist(data)
|
||||
elif data[0] == '[youtube]':
|
||||
self.pre_proc()
|
||||
elif data[0] == '[download]':
|
||||
self.download(data)
|
||||
elif data[0] == '[ffmpeg]':
|
||||
self.post_proc()
|
||||
|
||||
def finish(self):
|
||||
self.ListCtrl._write_data(self.index, 4, '')
|
||||
self.ListCtrl._write_data(self.index, 5, 'Finished')
|
||||
|
||||
def close(self):
|
||||
self.ListCtrl._write_data(self.index, 3, '')
|
||||
self.ListCtrl._write_data(self.index, 4, '')
|
||||
self.ListCtrl._write_data(self.index, 5, 'Stopped')
|
||||
|
||||
def error(self):
|
||||
self.ListCtrl._write_data(self.index, 3, '')
|
||||
self.ListCtrl._write_data(self.index, 4, '')
|
||||
self.ListCtrl._write_data(self.index, 5, 'Error')
|
||||
|
||||
def pre_proc(self):
|
||||
self.ListCtrl._write_data(self.index, 5, 'Pre-Processing %s' % self.info)
|
||||
|
||||
def post_proc(self):
|
||||
self.ListCtrl._write_data(self.index, 4, '')
|
||||
self.ListCtrl._write_data(self.index, 5, 'Converting to Audio %s' % self.info)
|
||||
|
||||
def download(self, data):
|
||||
self.ListCtrl._write_data(self.index, 1, data[3])
|
||||
self.ListCtrl._write_data(self.index, 2, data[1])
|
||||
self.ListCtrl._write_data(self.index, 3, data[7])
|
||||
self.ListCtrl._write_data(self.index, 4, data[5])
|
||||
self.ListCtrl._write_data(self.index, 5, 'Downloading %s' % self.info)
|
||||
|
||||
def playlist(self, data):
|
||||
self.ListCtrl._write_data(self.index, 1, '')
|
||||
self.ListCtrl._write_data(self.index, 2, '')
|
||||
self.ListCtrl._write_data(self.index, 3, '')
|
||||
self.ListCtrl._write_data(self.index, 4, '')
|
||||
self.info = '%s/%s' % (data[1], data[2])
|
||||
|
22
youtube_dl_gui/Utils.py
Normal file
22
youtube_dl_gui/Utils.py
Normal file
@ -0,0 +1,22 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
def remove_spaces(array):
|
||||
return [x for x in array if x != '']
|
||||
|
||||
def string_to_array(string, char=' '):
|
||||
return string.split(char)
|
||||
|
||||
def get_encoding():
|
||||
if sys.version_info >= (3, 0):
|
||||
return None
|
||||
|
||||
if sys.platform == 'win32':
|
||||
return sys.getfilesystemencoding()
|
||||
else:
|
||||
return None
|
||||
|
||||
def encode_list(data_list, encoding):
|
||||
return [x.encode(encoding, 'ignore') for x in data_list]
|
||||
|
@ -24,6 +24,7 @@ from .UpdateThread import UpdateThread
|
||||
from .DownloadThread import DownloadManager
|
||||
from .OptionsHandler import OptionsHandler
|
||||
from .YoutubeDLInterpreter import YoutubeDLInterpreter
|
||||
from .SignalHandler import DownloadHandler
|
||||
|
||||
if os.name == 'nt':
|
||||
YOUTUBE_DL_FILENAME = 'youtube-dl.exe'
|
||||
@ -93,8 +94,9 @@ class MainFrame(wx.Frame):
|
||||
# set publisher for download thread
|
||||
Publisher.subscribe(self.download_handler, "download")
|
||||
|
||||
# init options object
|
||||
# init Options and DownloadHandler objects
|
||||
self.optionsList = OptionsHandler()
|
||||
self.downloadHandler = None
|
||||
|
||||
# init some thread variables
|
||||
self.downloadThread = None
|
||||
@ -122,47 +124,16 @@ class MainFrame(wx.Frame):
|
||||
self.statusBar.SetLabel(msg)
|
||||
|
||||
def download_handler(self, msg):
|
||||
''' Handles msg base into signals see SIGNALS.txt for more info'''
|
||||
if msg.data[0] == 'finish':
|
||||
index = msg.data.pop()
|
||||
if index == -1:
|
||||
self.status_bar_write('Done')
|
||||
self.downloadButton.SetLabel('Download')
|
||||
self.updateButton.Enable()
|
||||
self.downloadThread = None
|
||||
self.urlList = []
|
||||
else:
|
||||
self.statusList._write_data(index, 4, '')
|
||||
self.statusList._write_data(index, 5, 'Finished')
|
||||
elif msg.data[0] == 'close':
|
||||
index = msg.data.pop()
|
||||
if index == -1:
|
||||
self.status_bar_write('Stoping downloads')
|
||||
else:
|
||||
self.statusList._write_data(index, 3, '')
|
||||
self.statusList._write_data(index, 4, '')
|
||||
self.statusList._write_data(index, 5, 'Stopped')
|
||||
elif msg.data[0] == 'error':
|
||||
index = msg.data.pop()
|
||||
self.statusList._write_data(index, 3, '')
|
||||
self.statusList._write_data(index, 4, '')
|
||||
self.statusList._write_data(index, 5, 'Error')
|
||||
elif msg.data[0] == '[youtube]':
|
||||
index = msg.data.pop()
|
||||
self.statusList._write_data(index, 5, 'Pre-Processing')
|
||||
elif msg.data[0] == '[download]':
|
||||
index = msg.data.pop()
|
||||
self.statusList._write_data(index, 1, msg.data[3])
|
||||
self.statusList._write_data(index, 2, msg.data[1])
|
||||
self.statusList._write_data(index, 3, msg.data[7])
|
||||
self.statusList._write_data(index, 4, msg.data[5])
|
||||
self.statusList._write_data(index, 5, 'Downloading')
|
||||
elif msg.data[0] == '[ffmpeg]':
|
||||
index = msg.data.pop()
|
||||
self.statusList._write_data(index, 4, '')
|
||||
self.statusList._write_data(index, 5, 'Converting to Audio')
|
||||
else: # ['ignore'] or anything else
|
||||
pass # do nothing
|
||||
self.downloadHandler.handle(msg)
|
||||
if self.downloadHandler._has_closed():
|
||||
self.status_bar_write('Stoping downloads')
|
||||
if self.downloadHandler._has_finished():
|
||||
self.status_bar_write('Done')
|
||||
self.downloadButton.SetLabel('Download')
|
||||
self.updateButton.Enable()
|
||||
self.downloadThread = None
|
||||
self.urlList = []
|
||||
self.downloadHandler = None
|
||||
|
||||
def update_handler(self, msg):
|
||||
if msg.data == 'finish':
|
||||
@ -187,6 +158,7 @@ class MainFrame(wx.Frame):
|
||||
options = YoutubeDLInterpreter(self.optionsList, YOUTUBE_DL_FILENAME).get_options()
|
||||
self.status_bar_write('Download started')
|
||||
self.downloadThread = DownloadManager(options, self.statusList._get_items())
|
||||
self.downloadHandler = DownloadHandler(self.statusList)
|
||||
self.downloadButton.SetLabel('Stop')
|
||||
self.updateButton.Disable()
|
||||
|
||||
@ -238,7 +210,7 @@ class ListCtrl(wx.ListCtrl):
|
||||
self.InsertColumn(2, 'Percent', width=80)
|
||||
self.InsertColumn(3, 'ETA', width=50)
|
||||
self.InsertColumn(4, 'Speed', width=90)
|
||||
self.InsertColumn(5, 'Status', width=120)
|
||||
self.InsertColumn(5, 'Status', width=150)
|
||||
self.ListIndex = 0
|
||||
|
||||
''' Add single item on list '''
|
||||
|
@ -1 +1 @@
|
||||
__version__ = '0.2'
|
||||
__version__ = '0.2.1'
|
||||
|
Loading…
x
Reference in New Issue
Block a user