Browse Source

Rerite DownloadThread.py using DownloadObject

Remove OutputHandler.py
	Now DownloadThread talks directly on
	ListCtrl using write() method.

Add DownloadObject.py
	Now DownloadObject is responsible for
	downloading the video and not the
	DownloadThread.

Replaced DownloadThread.ProcessWrapper with
	 DownloadThread.DownloadThread
doc-issue-template
MrS0m30n3 10 years ago
parent
commit
8bc4b8a978
8 changed files with 413 additions and 381 deletions
  1. 224
      youtube_dl_gui/DownloadObject.py
  2. 205
      youtube_dl_gui/DownloadThread.py
  3. 3
      youtube_dl_gui/LogManager.py
  4. 1
      youtube_dl_gui/OptionsHandler.py
  5. 191
      youtube_dl_gui/OutputHandler.py
  6. 7
      youtube_dl_gui/Utils.py
  7. 139
      youtube_dl_gui/YoutubeDLGUI.py
  8. 24
      youtube_dl_gui/YoutubeDLInterpreter.py

224
youtube_dl_gui/DownloadObject.py

@ -0,0 +1,224 @@
#! /usr/bin/env python
import subprocess
from .Utils import (
get_encoding,
get_filename,
encode_list,
os_type
)
class DownloadObject(object):
'''
Download videos using youtube-dl & subprocess.
Params
youtubedl_path: Absolute path of youtube-dl.
data_hook: Can be any function with one parameter, the data.
logger: Can be any logger which implements log().
Accessible Methods
download()
Params: URL to download
Options list e.g. ['--help']
Return: On download error return False else True.
stop()
Params: None
Acessible Variables
files_list: Python list that contains all the files DownloadObject
instance has downloaded.
Data_hook Keys
See self._init_data().
'''
STDERR_IGNORE = '' # Default filter for our self._log() method
def __init__(self, youtubedl_path, data_hook=None, logger=None):
self.youtubedl_path = youtubedl_path
self.data_hook = data_hook
self.logger = logger
self.files_list = []
self._proc = None
self._init_data()
def _init_data(self):
''' Keep the __init__() clean. '''
self._data = {
'playlist_index': None,
'playlist_size': None,
'filesize': None,
'filename': None,
'percent': None,
'status': None,
'speed': None,
'eta': None
}
def download(self, url, options):
''' Download url using given options list. '''
error = False
cmd = self._get_cmd(url, options)
cmd = self._encode_cmd(cmd)
info = self._get_process_info()
self._proc = self._create_process(cmd, info)
while self._proc_is_alive():
stdout, stderr = self._read()
data = extract_data(stdout)
synced = self._sync_data(data)
if stderr != '':
error = True
if self.logger is not None:
self._log(stderr)
if self.data_hook is not None and synced:
self._hook_data()
return (not error)
def stop(self):
''' Stop download process. '''
if self._proc is not None:
self._proc.kill()
def _sync_data(self, data):
''' Sync data between extract_data() dictionary and self._data.
Return True if synced else return False.
'''
synced = False
for key in data:
if key == 'filename':
# Save full file path on files_list
self._add_on_files_list(data['filename'])
# Keep only the filename not the path on data['filename']
data['filename'] = get_filename(data['filename'])
self._data[key] = data[key]
synced = True
return synced
def _add_on_files_list(self, filename):
''' Add filename on files_list. '''
self.files_list.append(filename)
def _log(self, data):
if data != self.STDERR_IGNORE:
self.logger.log(data)
def _hook_data(self):
''' Pass self._data back to data_hook. '''
self.data_hook(self._data)
def _proc_is_alive(self):
''' Return True if self._proc is alive. '''
if self._proc is None:
return False
return self._proc.poll() is None
def _read(self):
''' Read subprocess stdout, stderr. '''
stdout = self._read_stdout()
if stdout == '':
stderr = self._read_stderr()
else:
stderr = ''
return stdout, stderr
def _read_stdout(self):
''' Read subprocess stdout. '''
if self._proc is None:
return ''
stdout = self._proc.stdout.readline()
return stdout.rstrip()
def _read_stderr(self):
''' Read subprocess stderr. '''
if self._proc is None:
return ''
stderr = self._proc.stderr.readline()
return stderr.rstrip()
def _create_process(self, cmd, info):
return subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
startupinfo=info)
def _get_cmd(self, url, options):
''' Return command for subprocess. '''
if os_type == 'nt':
cmd = [self.youtubedl_path] + options + [url]
else:
cmd = ['python', self.youtubedl_path] + options + [url]
return cmd
def _encode_cmd(self, cmd):
''' Encode command for subprocess.
Refer to http://stackoverflow.com/a/9951851/35070
'''
encoding = get_encoding()
if encoding is not None:
cmd = encode_list(cmd, encoding)
return cmd
def _get_process_info(self):
''' Hide subprocess window on Windows. '''
if os_type == 'nt':
info = subprocess.STARTUPINFO()
info.dwFlags |= subprocess.STARTF_USESHOWWINDOW
return info
else:
return None
def extract_data(stdout):
''' Extract data from youtube-dl stdout. '''
data_dictionary = {}
stdout = [s for s in stdout.split(' ') if s != '']
if len(stdout) == 0:
return data_dictionary
header = stdout.pop(0).replace('[', '').replace(']', '')
if header == 'download':
data_dictionary['status'] = 'download'
if stdout[0] == 'Destination:':
data_dictionary['filename'] = ' '.join(stdout[1:])
elif '%' in stdout[0]:
if stdout[0] == '100%':
data_dictionary['speed'] = ''
else:
data_dictionary['percent'] = stdout[0]
data_dictionary['filesize'] = stdout[2]
data_dictionary['speed'] = stdout[4]
data_dictionary['eta'] = stdout[6]
elif stdout[0] == 'Downloading' and stdout[1] == 'video':
data_dictionary['playlist_index'] = stdout[2]
data_dictionary['playlist_size'] = stdout[4]
if header == 'ffmpeg':
data_dictionary['status'] = 'post_process'
if header == 'youtube':
data_dictionary['status'] = 'pre_process'
return data_dictionary

205
youtube_dl_gui/DownloadThread.py

@ -1,6 +1,5 @@
#! /usr/bin/env python
import subprocess
from time import sleep
from threading import Thread
@ -8,30 +7,27 @@ from wx import CallAfter
from wx.lib.pubsub import setuparg1
from wx.lib.pubsub import pub as Publisher
from .OutputHandler import (
DataPack,
OutputFormatter
)
from .YoutubeDLInterpreter import YoutubeDLInterpreter
from .DownloadObject import DownloadObject
from .Utils import (
get_encoding,
encode_list,
get_youtubedl_filename,
remove_file,
os_type,
file_exist
file_exist,
fix_path
)
MAX_DOWNLOAD_THREADS = 3
PUBLISHER_TOPIC = 'download'
class DownloadManager(Thread):
def __init__(self, options, downloadlist, clear_dash_files, logmanager=None):
PUBLISHER_TOPIC = 'download_manager'
MAX_DOWNLOAD_THREADS = 3
def __init__(self, downloadlist, opt_manager, logmanager=None):
super(DownloadManager, self).__init__()
self.clear_dash_files = clear_dash_files
self.downloadlist = downloadlist
self.opt_manager = opt_manager
self.logmanager = logmanager
self.options = options
self.running = True
self.kill = False
self.procList = []
@ -44,7 +40,7 @@ class DownloadManager(Thread):
# Extract url, index from data
url, index = self.extract_data()
# Wait for your turn if there are not more positions in 'queue'
while self.procNo >= MAX_DOWNLOAD_THREADS:
while self.procNo >= self.MAX_DOWNLOAD_THREADS:
proc = self.check_queue()
if proc != None:
self.procList.remove(proc)
@ -53,11 +49,10 @@ class DownloadManager(Thread):
# If we still running create new ProcessWrapper thread
if self.running:
self.procList.append(
ProcessWrapper(
self.options,
DownloadThread(
url,
index,
self.clear_dash_files,
self.opt_manager,
self.logmanager
)
)
@ -71,7 +66,7 @@ class DownloadManager(Thread):
# If we reach here close down all child threads
self.terminate_all()
if not self.kill:
CallAfter(Publisher.sendMessage, PUBLISHER_TOPIC, DataPack('finish'))
self._callafter('finish')
def downloading(self):
for proc in self.procList:
@ -100,98 +95,100 @@ class DownloadManager(Thread):
if not proc.isAlive():
return proc
return None
def _callafter(self, data):
CallAfter(Publisher.sendMessage, self.PUBLISHER_TOPIC, data)
def close(self, kill=False):
self.kill = kill
self.procNo = 0
self.running = False
CallAfter(Publisher.sendMessage, PUBLISHER_TOPIC, DataPack('close'))
class ProcessWrapper(Thread):
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._callafter('close')
class DownloadThread(Thread):
'''
Params
url: URL to download.
index: ListCtrl index for the current DownloadThread.
opt_manager: OptionsHandler.OptionsHandler object.
log_manager: Any logger which implements log().
Accessible Methods
close()
Params: None
'''
PUBLISHER_TOPIC = 'download_thread'
def __init__(self, url, index, opt_manager, log_manager=None):
super(DownloadThread, self).__init__()
self.log_manager = log_manager
self.opt_manager = opt_manager
self.index = index
self.log = log
self.url = url
self.filenames = []
self.stopped = False
self.error = False
self.proc = None
self._dl_object = None
self.start()
def run(self):
self.proc = self.create_process(self.get_cmd(), self.get_process_info())
# while subprocess is alive and NOT the current thread
while self.proc_is_alive():
# read stdout, stderr from proc
stdout, stderr = self.read()
if stdout != '':
# pass stdout to output formatter
data = OutputFormatter(stdout).get_data()
if self.clear_dash_files: self.add_file(data)
# add index to data pack
data.index = self.index
# send data back to caller
CallAfter(Publisher.sendMessage, PUBLISHER_TOPIC, data)
if stderr != '':
self.error = True
self.write_to_log(stderr)
if not self.stopped:
if self.clear_dash_files:
self.clear_dash()
if not self.error:
CallAfter(Publisher.sendMessage, PUBLISHER_TOPIC, DataPack('finish', self.index))
else:
CallAfter(Publisher.sendMessage, PUBLISHER_TOPIC, DataPack('error', self.index))
def add_file(self, dataPack):
if dataPack.header == 'filename':
self.filenames.append(dataPack.data)
def write_to_log(self, data):
if self.log != None:
self.log.write(data)
def clear_dash(self):
CallAfter(Publisher.sendMessage, PUBLISHER_TOPIC, DataPack('remove', self.index))
for f in self.filenames:
if file_exist(f):
remove_file(f)
def close(self):
self.proc.kill()
self.stopped = True
CallAfter(Publisher.sendMessage, PUBLISHER_TOPIC, DataPack('close', self.index))
def proc_is_alive(self):
return self.proc.poll() == None
def read(self):
stdout = ''
stderr = ''
stdout = self.proc.stdout.readline()
if stdout == '':
stderr = self.proc.stderr.readline()
return stdout.rstrip(), stderr.rstrip()
def create_process(self, cmd, info):
return subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, startupinfo=info)
def get_cmd(self):
enc = get_encoding()
if enc != None:
cmd = encode_list(self.options + [self.url], enc)
youtubedl_path = self._get_youtubedl_path()
options = YoutubeDLInterpreter(self.opt_manager).get_options()
self._dl_object = DownloadObject(youtubedl_path, self._data_hook, self.log_manager)
success = self._dl_object.download(self.url, options)
if self.opt_manager.options['clear_dash_files']:
self._clear_dash()
if success:
self._callafter(self._get_status_pack('Finished'))
else:
cmd = self.options + [self.url]
return cmd
def get_process_info(self):
if os_type == 'nt':
info = subprocess.STARTUPINFO()
info.dwFlags |= subprocess.STARTF_USESHOWWINDOW
return info
self._callafter(self._get_status_pack('Error'))
def close(self):
if self._dl_object is not None:
self._callafter(self._get_status_pack('Stopping'))
self._dl_object.stop()
def _clear_dash(self):
''' Clear DASH files after ffmpeg mux '''
for fl in self._dl_object.files_list:
if file_exist(fl):
remove_file(fl)
def _data_hook(self, data):
''' Add download index and send data back to caller '''
data['index'] = self.index
data['status'] = self._get_status(data)
self._callafter(data)
def _callafter(self, data):
CallAfter(Publisher.sendMessage, self.PUBLISHER_TOPIC, data)
def _get_status_pack(self, message):
''' Return simple status pack '''
data = {'index': self.index, 'status': message}
return data
def _get_status(self, data):
''' Return download process status '''
if data['playlist_index'] is not None:
playlist_info = '%s/%s' % (data['playlist_index'], data['playlist_size'])
else:
return None
playlist_info = ''
if data['status'] == 'pre_process':
msg = 'Pre-Processing %s' % playlist_info
elif data['status'] == 'download':
msg = 'Downloading %s' % playlist_info
elif data['status'] == 'post_process':
msg = 'Post-Processing %s' % playlist_info
return msg
def _get_youtubedl_path(self):
''' Retrieve youtube-dl path '''
path = self.opt_manager.options['youtubedl_path']
path = fix_path(path) + get_youtubedl_filename()
return path

3
youtube_dl_gui/LogManager.py

@ -35,6 +35,9 @@ class LogManager():
with open(self.path, 'w') as fl:
fl.write('')
def log(self, data):
self.write(data)
def write(self, data):
with open(self.path, 'a') as fl:
if self.add_time:

1
youtube_dl_gui/OptionsHandler.py

@ -8,7 +8,6 @@ from .Utils import (
get_user_config_path,
get_HOME,
file_exist,
os_type,
fix_path,
check_path
)

191
youtube_dl_gui/OutputHandler.py

@ -1,191 +0,0 @@
#! /usr/bin/env python
from .Utils import (
remove_empty_items,
string_to_array,
get_filename
)
class DownloadHandler():
def __init__(self, ListCtrl):
self.ListCtrl = ListCtrl
self.finished = False
self.closed = False
self.error = False
self.init_handlers()
def init_handlers(self):
''' Initialise handlers '''
self.handlers = [None for i in range(self.ListCtrl.ListIndex)]
def _has_closed(self):
return self.closed
def _has_finished(self):
return self.finished
def _has_error(self):
return self.error
def _add_empty_handler(self):
self.handlers.append(None)
def handle(self, msg):
''' Handles msg base to Signals.txt '''
pack = msg.data
if pack.index == -1:
self.global_handler(pack)
else:
self.index_handler(pack)
def global_handler(self, pack):
''' Manage global index = -1 '''
if pack.header == 'close':
self.closed = True
elif pack.header == 'finish':
self.finished = True
def index_handler(self, pack):
''' Manage handlers base on index '''
if self.handlers[pack.index] == None:
self.handlers[pack.index] = IndexDownloadHandler(self.ListCtrl, pack.index)
self.handlers[pack.index].handle(pack)
if self.handlers[pack.index].has_error():
self.error = True
class IndexDownloadHandler():
def __init__(self, ListCtrl, index):
self.ListCtrl = ListCtrl
self.index = index
self.err = False
self.info = ''
def has_error(self):
return self.err
def handle(self, pack):
''' Handle its pack for current index '''
if pack.header == 'finish':
self.finish()
elif pack.header == 'close':
self.close()
elif pack.header == 'error':
self.error()
elif pack.header == 'playlist':
self.playlist(pack.data)
elif pack.header == 'youtube':
self.pre_proc()
elif pack.header == 'download':
self.download(pack.data)
elif pack.header == 'ffmpeg':
self.post_proc()
elif pack.header == 'remove':
self.remove()
elif pack.header == 'filename':
self.filename(pack.data)
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.err = True
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, 'Post-Processing %s' % self.info)
def download(self, data):
self.ListCtrl._write_data(self.index, 1, data[0])
self.ListCtrl._write_data(self.index, 2, data[1])
self.ListCtrl._write_data(self.index, 3, data[2])
self.ListCtrl._write_data(self.index, 4, data[3])
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[0], data[1])
def remove(self):
self.ListCtrl._write_data(self.index, 5, 'Removing DASH Files')
def filename(self, fl):
self.ListCtrl._write_data(self.index, 0, get_filename(fl))
class DataPack():
def __init__(self, header, index=-1, data=None):
self.header = header
self.index = index
self.data = data
class OutputFormatter():
def __init__(self, stdout):
dataPack = None
self.stdout = remove_empty_items(string_to_array(stdout))
# extract header from stdout
header = self.extract_header()
# extract special headers filename, playlist
header = self.set_filename_header(header)
header = self.set_playlist_header(header)
# extract data base on header
data = self.extract_data(header)
# extract special ignore header base on header, data
header = self.set_ignore_header(header, data)
# create data pack
self.dataPack = DataPack(header, data=data)
def extract_header(self):
header = self.stdout.pop(0).replace('[', '').replace(']', '')
return header
def extract_data(self, header):
''' Extract data base on header '''
if header == 'download':
if '%' in self.stdout[0]:
if self.stdout[0] != '100%':
''' size, percent, eta, speed '''
return [self.stdout[2], self.stdout[0], self.stdout[6], self.stdout[4]]
if header == 'playlist':
return [self.stdout[2], self.stdout[4]]
if header == 'filename':
return ' '.join(self.stdout[1:])
return None
def set_filename_header(self, header):
if header != 'ffmpeg':
if self.stdout[0] == 'Destination:':
return 'filename'
return header
def set_playlist_header(self, header):
if header == 'download':
if self.stdout[0] == 'Downloading' and self.stdout[1] == 'video':
return 'playlist'
return header
def set_ignore_header(self, header, data):
if header == 'download' and data == None:
return 'ignore'
return header
def get_data(self):
return self.dataPack

7
youtube_dl_gui/Utils.py

@ -37,7 +37,6 @@ def get_encoding():
if sys.version_info >= (3, 0):
return None
if sys.platform == 'win32':
# Refer to http://stackoverflow.com/a/9951851/35070
return preferredencoding()
return None
@ -86,6 +85,12 @@ def check_path(path):
if not file_exist(path):
makedir(path)
def get_youtubedl_filename():
youtubedl_fl = 'youtube-dl'
if os_type == 'nt':
youtubedl_fl += '.exe'
return youtubedl_fl
def get_user_config_path():
if os_type == 'nt':
path = os.getenv('APPDATA')

139
youtube_dl_gui/YoutubeDLGUI.py

@ -10,8 +10,7 @@ from .version import __version__
from .UpdateThread import UpdateThread
from .DownloadThread import DownloadManager
from .OptionsHandler import OptionsHandler
from .YoutubeDLInterpreter import YoutubeDLInterpreter
from .OutputHandler import DownloadHandler
from .LogManager import LogManager, LogGUI
from .Utils import (
video_is_dash,
@ -88,11 +87,11 @@ class MainFrame(wx.Frame):
Publisher.subscribe(self.update_handler, "update")
# set publisher for download thread
Publisher.subscribe(self.download_handler, "download")
Publisher.subscribe(self.download_handler, "download_manager")
Publisher.subscribe(self.download_handler, "download_thread")
# init Options and DownloadHandler objects
# init Options
self.optManager = OptionsHandler()
self.downloadHandler = None
# init log manager
self.logManager = None
@ -158,13 +157,11 @@ class MainFrame(wx.Frame):
def status_bar_write(self, msg):
self.statusBar.SetLabel(msg)
def fin_task(self, msg):
self.status_bar_write(msg)
def fin_tasks(self):
self.downloadButton.SetLabel('Download')
self.updateButton.Enable()
self.downloadThread.join()
self.downloadThread = None
self.downloadHandler = None
self.urlList = []
if self.optManager.options['shutdown']:
shutdown_sys(self.optManager.options['sudo_password'])
@ -177,18 +174,18 @@ class MainFrame(wx.Frame):
open_dir(self.optManager.options['save_path'])
def download_handler(self, msg):
self.downloadHandler.handle(msg)
if self.downloadHandler._has_closed():
self.status_bar_write('Stoping downloads')
if self.downloadHandler._has_finished():
if self.downloadHandler._has_error():
if self.logManager != None:
msg = 'An error occured while downloading. See Options>Log.'
else:
msg = 'An error occured while downloading'
else:
msg = 'Done'
self.fin_task(msg)
topic = msg.topic[0]
data = msg.data
if topic == 'download_thread':
self.statusList.write(data)
if topic == 'download_manager':
if data == 'close':
self.status_bar_write('Stopping downloads')
elif data == 'finish':
self.status_bar_write('Done')
self.fin_tasks()
def update_handler(self, msg):
if msg.data == 'finish':
@ -206,20 +203,19 @@ class MainFrame(wx.Frame):
url = remove_spaces(url)
if url != '':
self.urlList.append(url)
self.statusList._add_item(url)
self.statusList.add_item(url)
def start_download(self):
self.statusList._clear_list()
self.statusList.clear_list()
self.load_tracklist(self.trackList.GetValue().split('\n'))
if not self.statusList._is_empty():
options = YoutubeDLInterpreter(self.optManager, YOUTUBE_DL_FILENAME).get_options()
if not self.statusList.is_empty():
self.downloadThread = DownloadManager(
options,
self.statusList._get_items(),
self.optManager.options['clear_dash_files'],
self.statusList.get_items(),
self.optManager,
self.logManager
)
self.downloadHandler = DownloadHandler(self.statusList)
self.status_bar_write('Download started')
self.downloadButton.SetLabel('Stop')
self.updateButton.Disable()
@ -257,12 +253,10 @@ class MainFrame(wx.Frame):
if url not in self.urlList and url != '':
''' Add url into original download list '''
self.urlList.append(url)
''' Add handler for url '''
self.downloadHandler._add_empty_handler()
''' Add url into statusList '''
self.statusList._add_item(url)
self.statusList.add_item(url)
''' Retrieve last item as {url:url, index:indexNo} '''
item = self.statusList._get_last_item()
item = self.statusList.get_last_item()
''' Pass that item into downloadThread '''
self.downloadThread._add_download_item(item)
@ -291,7 +285,19 @@ class MainFrame(wx.Frame):
self.Destroy()
class ListCtrl(wx.ListCtrl, ListCtrlAutoWidthMixin):
''' Custom ListCtrl class '''
# Hold column for each data
DATA_COLUMNS = {
'filename': 0,
'filesize': 1,
'percent': 2,
'status': 5,
'speed': 4,
'eta': 3
}
def __init__(self, parent=None, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0):
wx.ListCtrl.__init__(self, parent, id, pos, size, style)
ListCtrlAutoWidthMixin.__init__(self)
@ -302,44 +308,53 @@ class ListCtrl(wx.ListCtrl, ListCtrlAutoWidthMixin):
self.InsertColumn(4, 'Speed', width=90)
self.InsertColumn(5, 'Status', width=160)
self.setResizeColumn(0)
self.ListIndex = 0
''' Add single item on list '''
def _add_item(self, item):
self.InsertStringItem(self.ListIndex, item)
self.ListIndex += 1
self.list_index = 0
''' Write data on index, column '''
def _write_data(self, index, column, data):
self.SetStringItem(index, column, data)
def write(self, data):
''' Write data on ListCtrl '''
index = data['index']
for key in data:
if key in self.DATA_COLUMNS:
self._write_data(data[key], index, self.DATA_COLUMNS[key])
def add_item(self, item):
''' Add single item on ListCtrl '''
self.InsertStringItem(self.list_index, item)
self.list_index += 1
''' Clear list and set index to 0'''
def _clear_list(self):
def clear_list(self):
self.DeleteAllItems()
self.ListIndex = 0
self.list_index = 0
''' Return True if list is empty '''
def _is_empty(self):
return self.ListIndex == 0
def is_empty(self):
return self.list_index == 0
def get_items(self, start_index=0):
''' Return list of items starting from start_index '''
items = []
for row in range(start_index, self.list_index):
item = self._get_item(row)
items.append(item)
return items
def get_last_item(self):
''' Return last item of ListCtrl '''
return self._get_item(self.list_index - 1)
def _write_data(self, data, row, column):
''' Write data on row, column '''
if isinstance(data, basestring):
self.SetStringItem(row, column, data)
''' Get last item inserted, Returns dictionary '''
def _get_last_item(self):
def _get_item(self, index):
''' Return single item from index '''
data = {}
last_item = self.GetItem(itemId=self.ListIndex-1, col=0)
data['url'] = last_item.GetText()
data['index'] = self.ListIndex-1
item = self.GetItem(itemId=index, col=0)
data['url'] = item.GetText()
data['index'] = index
return data
''' Retrieve all items [start, self.ListIndex), Returns list '''
def _get_items(self, start=0):
items = []
for row in range(start, self.ListIndex):
item = self.GetItem(itemId=row, col=0)
data = {}
data['url'] = item.GetText()
data['index'] = row
items.append(data)
return items
class LogPanel(wx.Panel):

24
youtube_dl_gui/YoutubeDLInterpreter.py

@ -1,18 +1,8 @@
#! /usr/bin/env python
'''
Parse OptionHandler object into list
and call youtube_dl.main(list) using
subprocess (we use this method to let
youtube_dl.main() handle all the hard
work)
'''
from .Utils import (
video_is_dash,
os_type,
fix_path,
add_PATH
fix_path
)
LANGUAGES = {"English":"en",
@ -45,11 +35,9 @@ AUDIO_Q = {"high":"0",
class YoutubeDLInterpreter():
def __init__(self, optManager, youtubeDLFile):
self.youtubeDLFile = youtubeDLFile
def __init__(self, optManager):
self.optManager = optManager
self.opts = []
self.set_os()
self.set_progress_opts()
self.set_output_opts()
self.set_auth_opts()
@ -64,14 +52,6 @@ class YoutubeDLInterpreter():
def get_options(self):
return self.opts
def set_os(self):
if os_type == 'nt':
self.opts = [self.youtubeDLFile]
add_PATH(self.optManager.options['youtubedl_path'])
else:
path = fix_path(self.optManager.options['youtubedl_path'])
self.opts = ['python', path + self.youtubeDLFile]
def set_progress_opts(self):
''' Do NOT change this option '''
self.opts.append('--newline')

Loading…
Cancel
Save