Update to v1.1.050
This commit is contained in:
parent
454eb9933d
commit
9efcfdd128
11
.gitignore
vendored
11
.gitignore
vendored
@ -1,11 +0,0 @@
|
||||
# This file copied from
|
||||
# https://python-packaging.readthedocs.io/en/latest/minimal.html?highlight=gitignore
|
||||
|
||||
# Compiled python modules.
|
||||
*.pyc
|
||||
|
||||
# Setuptools distribution folder.
|
||||
/dist/
|
||||
|
||||
# Python egg metadata, regenerated from source files by setuptools.
|
||||
/*.egg-info
|
@ -1,32 +1,38 @@
|
||||
Tartube installation problems on MS Windows
|
||||
===========================================
|
||||
|
||||
Some users on MS Windows report that they can't run Tartube at all.
|
||||
Some users on MS Windows report that they can't run Tartube at all. There are three possible fixes.
|
||||
|
||||
This page describes what you can do, if you are one of them.
|
||||
Fix #1
|
||||
~~~~~~
|
||||
|
||||
The problem
|
||||
~~~~~~~~~~~
|
||||
Wait for v1.2 of Tartube, which should fix the problem.
|
||||
|
||||
A full installation of Tartube and all of its dependencies uses over 2GB of your hard drive. The download is over 600MB.
|
||||
Fix #2
|
||||
~~~~~~
|
||||
|
||||
This is obviously too much, so I've removed everything that is not necessary. As a result, the installer is a 90MB download.
|
||||
Find the **tartube_mswin.sh** file, and modify it.
|
||||
|
||||
The installer works for most people, but some users are reporting that they can't run Tartube at all.
|
||||
If you used the MS Windows installer, it should be installed in
|
||||
|
||||
Obviously, something is missing from the installer. I can't reproduce the problem on any computer, so I don't know what is missing.
|
||||
**C:\\Users\\YOURNAME\\AppData\\Local\\Tartube\\msys64\\home\\user\\tartube**
|
||||
|
||||
The solution
|
||||
~~~~~~~~~~~~
|
||||
(You may have to `make hidden folders visible <https://support.microsoft.com/en-us/help/14201/windows-show-hidden-files>`__ to see the parent folder.)
|
||||
|
||||
A workaround is to perform a manual installation. This takes about 10-30 minutes, depending on your internet speed.
|
||||
Open the file in a text editor, and replace this line
|
||||
|
||||
If the manual installation works, you can try to diagnose the original problem.
|
||||
**cd tartube**
|
||||
|
||||
As soon as someone discovers what is missing from the installer, I can add it, and everyone will be happy again.
|
||||
with this line
|
||||
|
||||
MS Windows manual installation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
**cd /home/user/tartube/tartube**
|
||||
|
||||
Save the file. You may now be able to run Tartube from the Windows Start Menu, or from the desktop shortcut.
|
||||
|
||||
Fix #3
|
||||
~~~~~~
|
||||
|
||||
Perform a manual installation. This takes about 10-30 minutes, depending on your internet speed.
|
||||
|
||||
- This section assumes you have a 64-bit computer
|
||||
- Download and install MSYS2 from `msys2.org <https://msys2.org>`__. You need the file that looks something like **msys2-x86_64-yyyymmdd.exe**
|
||||
@ -61,26 +67,3 @@ MS Windows manual installation
|
||||
|
||||
**python3 tartube**
|
||||
|
||||
Diagnosing the problem
|
||||
----------------------
|
||||
|
||||
If the manual installation works, and if you have the time and the patience, you can work out what the missing dependency is. When you find it, please `tell me <https://github.com/axcore/tartube/issues>`__.
|
||||
|
||||
- Download the normal installer from `Sourceforge <https://tartube.sourceforge.io/>`__
|
||||
- Run the installer. Tell it to install Tartube in **C:\\tartube**
|
||||
|
||||
.. image:: screenshots/diagnose1.png
|
||||
:alt: Set the installation folder
|
||||
|
||||
- You now have two installations - a working one in **C:\\msys64\\**, and a broken one in **C:\\tartube\\msys64\\**
|
||||
|
||||
.. image:: screenshots/diagnose2.png
|
||||
:alt: Picture of both folders
|
||||
|
||||
- Now, you can start moving files and folders from the working folder into the broken folder, **one at a time**
|
||||
- For example, you could move the file **C:\\msys64\\usr\\bin\\awk** to **C:\\tartube\\msys64\\usr\\bin\\awk**
|
||||
- For example, you could move the folder **C:\\msys64\\usr\\etc** to **C:\\tartube\\msys64\\usr\\bin\\etc**
|
||||
- Every time you copy something, try to run Tartube (from the Start menu, or from the desktop shortcut)
|
||||
- When Tartube runs for the first time, `tell me which file/folder you moved <https://github.com/axcore/tartube/issues>`__. I don't need to know everything - just tell me the **last** thing you moved.
|
||||
|
||||
|
||||
|
86
docs/mswin_install_old.rst
Normal file
86
docs/mswin_install_old.rst
Normal file
@ -0,0 +1,86 @@
|
||||
Tartube installation problems on MS Windows
|
||||
===========================================
|
||||
|
||||
Some users on MS Windows report that they can't run Tartube at all.
|
||||
|
||||
This page describes what you can do, if you are one of them.
|
||||
|
||||
The problem
|
||||
~~~~~~~~~~~
|
||||
|
||||
A full installation of Tartube and all of its dependencies uses over 2GB of your hard drive. The download is over 600MB.
|
||||
|
||||
This is obviously too much, so I've removed everything that is not necessary. As a result, the installer is a 90MB download.
|
||||
|
||||
The installer works for most people, but some users are reporting that they can't run Tartube at all.
|
||||
|
||||
Obviously, something is missing from the installer. I can't reproduce the problem on any computer, so I don't know what is missing.
|
||||
|
||||
The solution
|
||||
~~~~~~~~~~~~
|
||||
|
||||
A workaround is to perform a manual installation. This takes about 10-30 minutes, depending on your internet speed.
|
||||
|
||||
If the manual installation works, you can try to diagnose the original problem.
|
||||
|
||||
As soon as someone discovers what is missing from the installer, I can add it, and everyone will be happy again.
|
||||
|
||||
MS Windows manual installation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- This section assumes you have a 64-bit computer
|
||||
- Download and install MSYS2 from `msys2.org <https://msys2.org>`__. You need the file that looks something like **msys2-x86_64-yyyymmdd.exe**
|
||||
- MSYS2 wants to install in **C:\\msys64**, so do that
|
||||
- Open the MINGW64 terminal, which is **C:\\msys64\\mingw64.exe**
|
||||
- In the MINGW64 terminal, type:
|
||||
|
||||
**pacman -Syu**
|
||||
|
||||
- If the terminal wants to shut down, close it, and then restart it
|
||||
- Now type the following commands, one by one:
|
||||
|
||||
**pacman -Su**
|
||||
|
||||
**pacman -S mingw-w64-x86_64-python3**
|
||||
|
||||
**pacman -S mingw-w64-x86_64-python3-pip**
|
||||
|
||||
**pacman -S mingw-w64-x86_64-python3-gobject**
|
||||
|
||||
**pacman -S mingw-w64-x86_64-python3-requests**
|
||||
|
||||
**pacman -S mingw-w64-x86_64-gtk3**
|
||||
|
||||
**pacman -S mingw-w64-x86_64-gsettings-desktop-schemas**
|
||||
|
||||
- Download the `Tartube source code <https://sourceforge.net/projects/tartube/files/v0.7.0/tartube_v0.7.0.tar.gz/download>`__ from Sourceforge
|
||||
- Extract it into the folder **C:\\msys64\\home\\YOURNAME**, creating a folder called **C:\\msys64\\home\\YOURNAME\\tartube**
|
||||
- Now, to run Tartube, type these commands in the MINGW64 terminal:
|
||||
|
||||
**cd tartube**
|
||||
|
||||
**python3 tartube**
|
||||
|
||||
Diagnosing the problem
|
||||
----------------------
|
||||
|
||||
If the manual installation works, and if you have the time and the patience, you can work out what the missing dependency is. When you find it, please `tell me <https://github.com/axcore/tartube/issues>`__.
|
||||
|
||||
- Download the normal installer from `Sourceforge <https://tartube.sourceforge.io/>`__
|
||||
- Run the installer. Tell it to install Tartube in **C:\\tartube**
|
||||
|
||||
.. image:: screenshots/diagnose1.png
|
||||
:alt: Set the installation folder
|
||||
|
||||
- You now have two installations - a working one in **C:\\msys64\\**, and a broken one in **C:\\tartube\\msys64\\**
|
||||
|
||||
.. image:: screenshots/diagnose2.png
|
||||
:alt: Picture of both folders
|
||||
|
||||
- Now, you can start moving files and folders from the working folder into the broken folder, **one at a time**
|
||||
- For example, you could move the file **C:\\msys64\\usr\\bin\\awk** to **C:\\tartube\\msys64\\usr\\bin\\awk**
|
||||
- For example, you could move the folder **C:\\msys64\\usr\\etc** to **C:\\tartube\\msys64\\usr\\bin\\etc**
|
||||
- Every time you copy something, try to run Tartube (from the Start menu, or from the desktop shortcut)
|
||||
- When Tartube runs for the first time, `tell me which file/folder you moved <https://github.com/axcore/tartube/issues>`__. I don't need to know everything - just tell me the **last** thing you moved.
|
||||
|
||||
|
BIN
icons/small/archived.png
Normal file
BIN
icons/small/archived.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
BIN
icons/small/folder_black.png
Normal file
BIN
icons/small/folder_black.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
icons/small/folder_blue.png
Normal file
BIN
icons/small/folder_blue.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
icons/small/folder_green.png
Normal file
BIN
icons/small/folder_green.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
icons/small/folder_red.png
Normal file
BIN
icons/small/folder_red.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 451 B |
8
setup.py
8
setup.py
@ -34,8 +34,10 @@ import sys
|
||||
|
||||
|
||||
# For the Debian distribution, use an environment variable. When specified,
|
||||
# the default executable 'tartube' is replaced by the 'tartube_debian'
|
||||
# executiable, in which youtube-dl updates are disabled
|
||||
# the 'tartube_debian' file is the executable, rather than the 'tartube'
|
||||
# file
|
||||
# When the 'tartube_debian' file is the executable, youtube-dl updates are
|
||||
# disabled, and Tartube's config file is stored at $XDG_CONFIG_HOME
|
||||
# The package maintainer should use
|
||||
# TARTUBE_NO_UPDATES=1 python3 setup.py build
|
||||
env_var_name = 'TARTUBE_NO_UPDATES'
|
||||
@ -60,7 +62,7 @@ if env_var_value is not None:
|
||||
# Setup
|
||||
setuptools.setup(
|
||||
name='tartube',
|
||||
version='1.1.015',
|
||||
version='1.1.050',
|
||||
description='GUI front-end for youtube-dl',
|
||||
# long_description=long_description,
|
||||
long_description="""Tartube is a GUI front-end for youtube-dl, partly based
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -341,6 +341,53 @@ class DownloadManager(threading.Thread):
|
||||
break
|
||||
|
||||
|
||||
def check_master_slave(self, media_data_obj):
|
||||
|
||||
"""Called by VideoDownloader.do_download().
|
||||
|
||||
When two channels/playlists/folders share a download destination, we
|
||||
don't want to download both of them at the same time.
|
||||
|
||||
This function is called when media_data_obj is about to be
|
||||
downloaded.
|
||||
|
||||
Every worker is checked, to see if it's downloading to the same
|
||||
destination. If so, this function returns True, and
|
||||
VideoDownloader.do_download() waits a few seconds, before trying
|
||||
again.
|
||||
|
||||
Otherwise, this function returns False, and
|
||||
VideoDownloader.do_download() is free to start its download.
|
||||
|
||||
Args:
|
||||
|
||||
media_data_obj (media.Channel, media.Playlist, media.Folder):
|
||||
The media data object that the calling function wants to
|
||||
download
|
||||
|
||||
Returns:
|
||||
|
||||
True or False, as described above
|
||||
|
||||
"""
|
||||
|
||||
for worker_obj in self.worker_list:
|
||||
|
||||
if not worker_obj.available_flag \
|
||||
and worker_obj.download_item_obj:
|
||||
|
||||
other_obj = worker_obj.download_item_obj.media_data_obj
|
||||
|
||||
if other_obj.dbid != media_data_obj.dbid \
|
||||
and (
|
||||
other_obj.dbid == media_data_obj.master_dbid \
|
||||
or other_obj.dbid in media_data_obj.slave_dbid_list
|
||||
):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def check_workers_all_finished(self):
|
||||
|
||||
"""Called by self.run().
|
||||
@ -737,7 +784,7 @@ class DownloadList(object):
|
||||
|
||||
# Code
|
||||
# ----
|
||||
|
||||
|
||||
# For each media data object to be downloaded, created a
|
||||
# downloads.DownloadItem object, and update the IVs above
|
||||
if not media_data_obj:
|
||||
@ -763,7 +810,7 @@ class DownloadList(object):
|
||||
else:
|
||||
|
||||
# Use the specified media data object. The True value tells
|
||||
# self.create_item to download media_data_obj, even if it is a
|
||||
# self.create_item() to download media_data_obj, even if it is a
|
||||
# video in a channel or a playlist (which otherwise would be
|
||||
# handled by downloading the channel/playlist)
|
||||
self.create_item(media_data_obj, True)
|
||||
@ -810,8 +857,13 @@ class DownloadList(object):
|
||||
- media.Video objects in any restricted folder
|
||||
- media.Video objects in the fixed 'Unsorted Videos' folder which
|
||||
are already marked as downloaded
|
||||
- media.Video objects which have an ancestor (e.g. a parent
|
||||
media.Channel) for which checking/downloading is disabled
|
||||
- media.Channel and media.Playlist objects for which checking/
|
||||
downloading are disabled, or which have an ancestor (e.g. a
|
||||
parent media.folder) for which checking/downloading is disabled
|
||||
- media.Folder objects
|
||||
|
||||
|
||||
Adds the resulting downloads.DownloadItem object to this object's IVs.
|
||||
|
||||
Args:
|
||||
@ -855,6 +907,22 @@ class DownloadList(object):
|
||||
and not init_flag
|
||||
):
|
||||
return
|
||||
|
||||
# Don't create a download.DownloadItem object if the media data object
|
||||
# has an ancestor for which checking/downloading is disabled
|
||||
if isinstance(media_data_obj, media.Video):
|
||||
dl_disable_flag = False
|
||||
else:
|
||||
dl_disable_flag = media_data_obj.dl_disable_flag
|
||||
|
||||
parent_obj = media_data_obj.parent_obj
|
||||
|
||||
while not dl_disable_flag and parent_obj is not None:
|
||||
dl_disable_flag = parent_obj.dl_disable_flag
|
||||
parent_obj = parent_obj.parent_obj
|
||||
|
||||
if dl_disable_flag:
|
||||
return
|
||||
|
||||
# Don't create a download.DownloadItem object for a media.Folder,
|
||||
# obviously
|
||||
@ -1102,11 +1170,26 @@ class VideoDownloader(object):
|
||||
# The time (in seconds) between iterations of the loop in
|
||||
# self.do_download()
|
||||
self.sleep_time = 0.1
|
||||
# The time (in seconds) to wait for an existing download, which shares
|
||||
# a common download destination with this media data object, to
|
||||
# finish downloading
|
||||
self.long_sleep_time = 10
|
||||
|
||||
# Flag set to True if we are simulating downloads for this media data
|
||||
# object, or False if we actually downloading videos (set below)
|
||||
self.dl_sim_flag = None
|
||||
|
||||
# Flag set to True by a call from any function to self.stop_soon()
|
||||
# After being set to True, this VideoDownloader should give up after
|
||||
# the next call to self.confirm_new_video(), .confirm_old_video()
|
||||
# .confirm_sim_video()
|
||||
self.stop_soon_flag = False
|
||||
# When self.stop_soon_flag is True, the next call to
|
||||
# self.confirm_new_video(), .confirm_old_video() or
|
||||
# .confirm_sim_video() sets this flag to True, informing
|
||||
# self.do_download() that it can stop the child process
|
||||
self.stop_now_flag = False
|
||||
|
||||
# youtube-dl is passed a URL, which might represent an individual
|
||||
# video, a channel or a playlist
|
||||
# Assume it's an individual video unless youtube-dl reports a
|
||||
@ -1177,17 +1260,20 @@ class VideoDownloader(object):
|
||||
# download
|
||||
media_data_obj = self.download_item_obj.media_data_obj
|
||||
|
||||
# If the media data object is a video, channel or playlist, it can be
|
||||
# marked as a simulated download only
|
||||
# If it's a video inside a folder and the folder itself is marked as
|
||||
# simulated downloads only, apply that to all videos in the folder
|
||||
if self.download_manager_obj.force_sim_flag \
|
||||
or media_data_obj.dl_sim_flag \
|
||||
or (
|
||||
isinstance(media_data_obj, media.Video) \
|
||||
and isinstance(media_data_obj.parent_obj, media.Folder) \
|
||||
and media_data_obj.parent_obj.dl_sim_flag
|
||||
):
|
||||
# All media data objects can be marked as simulate downloads only. The
|
||||
# setting applies not just to the media data object, but all of its
|
||||
# descendants
|
||||
if self.download_manager_obj.force_sim_flag:
|
||||
dl_sim_flag = True
|
||||
else:
|
||||
dl_sim_flag = media_data_obj.dl_sim_flag
|
||||
parent_obj = media_data_obj.parent_obj
|
||||
|
||||
while not dl_sim_flag and parent_obj is not None:
|
||||
dl_sim_flag = parent_obj.dl_sim_flag
|
||||
parent_obj = parent_obj.parent_obj
|
||||
|
||||
if dl_sim_flag:
|
||||
self.dl_sim_flag = True
|
||||
self.video_num = 0
|
||||
self.video_total = 0
|
||||
@ -1229,6 +1315,18 @@ class VideoDownloader(object):
|
||||
# time it was checked/downloaded
|
||||
self.download_item_obj.media_data_obj.reset_error_warning()
|
||||
|
||||
# If two channels/playlists/folders share a download destination, we
|
||||
# don't want to download both of them at the same time
|
||||
# If this media data obj shares a download destination with another
|
||||
# downloads.DownloadWorker, wait until that download has finished
|
||||
# before starting this one
|
||||
if not isinstance(self.download_item_obj.media_data_obj, media.Video):
|
||||
|
||||
while self.download_manager_obj.check_master_slave(
|
||||
self.download_item_obj.media_data_obj,
|
||||
):
|
||||
time.sleep(self.long_sleep_time)
|
||||
|
||||
# Prepare a system command...
|
||||
cmd_list = self.get_system_cmd()
|
||||
# ...and create a new child process using that command
|
||||
@ -1307,6 +1405,12 @@ class VideoDownloader(object):
|
||||
+ ' to fetch a video\'s JSON data',
|
||||
)
|
||||
|
||||
# Stop this video downloader, if required to do so, having just
|
||||
# finished checking/downloading a video
|
||||
if self.stop_now_flag:
|
||||
self.stop()
|
||||
|
||||
|
||||
# The child process has finished
|
||||
while not self.stderr_queue.empty():
|
||||
|
||||
@ -1456,6 +1560,11 @@ class VideoDownloader(object):
|
||||
options_manager_obj.options_dict['keep_thumbnail'],
|
||||
)
|
||||
|
||||
# This VideoDownloader can now stop, if required to do so after a video
|
||||
# has been checked/downloaded
|
||||
if self.stop_soon_flag:
|
||||
self.stop_now_flag = True
|
||||
|
||||
|
||||
def confirm_old_video(self, dir_path, filename, extension):
|
||||
|
||||
@ -1549,16 +1658,37 @@ class VideoDownloader(object):
|
||||
= self.download_worker_obj.options_manager_obj
|
||||
|
||||
# Update the main window
|
||||
GObject.timeout_add(
|
||||
0,
|
||||
app_obj.announce_video_download,
|
||||
self.download_item_obj,
|
||||
video_obj,
|
||||
options_manager_obj.options_dict['keep_description'],
|
||||
options_manager_obj.options_dict['keep_info'],
|
||||
options_manager_obj.options_dict['keep_thumbnail'],
|
||||
)
|
||||
if media_data_obj.master_dbid != media_data_obj.dbid:
|
||||
|
||||
# The container is storing its videos in another
|
||||
# container's sub-directory, which (probably) explains
|
||||
# why we couldn't find a match. Don't add anything to the
|
||||
# Results List
|
||||
GObject.timeout_add(
|
||||
0,
|
||||
app_obj.announce_video_clone,
|
||||
video_obj,
|
||||
)
|
||||
|
||||
else:
|
||||
|
||||
# Do add an entry to the Results List (as well as updating
|
||||
# the Video Catalogue, as normal)
|
||||
GObject.timeout_add(
|
||||
0,
|
||||
app_obj.announce_video_download,
|
||||
self.download_item_obj,
|
||||
video_obj,
|
||||
options_manager_obj.options_dict['keep_description'],
|
||||
options_manager_obj.options_dict['keep_info'],
|
||||
options_manager_obj.options_dict['keep_thumbnail'],
|
||||
)
|
||||
|
||||
# This VideoDownloader can now stop, if required to do so after a video
|
||||
# has been checked/downloaded
|
||||
if self.stop_soon_flag:
|
||||
self.stop_now_flag = True
|
||||
|
||||
|
||||
def confirm_sim_video(self, json_dict):
|
||||
|
||||
@ -1851,6 +1981,11 @@ class VideoDownloader(object):
|
||||
if stop_flag:
|
||||
self.stop()
|
||||
|
||||
# This VideoDownloader can now stop, if required to do so after a video
|
||||
# has been checked/downloaded
|
||||
elif self.stop_soon_flag:
|
||||
self.stop_now_flag = True
|
||||
|
||||
|
||||
def create_child_process(self, cmd_list):
|
||||
|
||||
@ -2243,6 +2378,9 @@ class VideoDownloader(object):
|
||||
if DEBUG_FUNC_FLAG:
|
||||
print('dl 1997 get_system_cmd')
|
||||
|
||||
# Import things for convenience
|
||||
app_obj = self.download_manager_obj.app_obj
|
||||
media_data_obj = self.download_item_obj.media_data_obj
|
||||
options_list = self.download_worker_obj.options_list
|
||||
|
||||
# Simulate the download, rather than actually downloading videos, if
|
||||
@ -2250,13 +2388,30 @@ class VideoDownloader(object):
|
||||
if self.dl_sim_flag:
|
||||
options_list.append('--dump-json')
|
||||
|
||||
# If actually downloading videos, create an archive file so that, if
|
||||
# the user deletes the videos, youtube-dl won't try to download them
|
||||
# again
|
||||
else:
|
||||
|
||||
# (Create the archive file in the media data object's own
|
||||
# sub-directory, not the alternative download destination, as
|
||||
# this helps youtube-dl to work the way we want it)
|
||||
if isinstance(media_data_obj, media.Video):
|
||||
dl_path = media_data_obj.parent_obj.get_dir(app_obj)
|
||||
else:
|
||||
dl_path = media_data_obj.get_dir(app_obj)
|
||||
|
||||
options_list.append('--download-archive')
|
||||
options_list.append(
|
||||
os.path.abspath(os.path.join(dl_path, 'ytdl-archive.txt')),
|
||||
)
|
||||
|
||||
# Show verbose output (youtube-dl debugging mode), if required
|
||||
if self.download_manager_obj.app_obj.ytdl_write_verbose_flag:
|
||||
if app_obj.ytdl_write_verbose_flag:
|
||||
options_list.append('--verbose')
|
||||
|
||||
# Set the list
|
||||
cmd_list = [self.download_manager_obj.app_obj.ytdl_path] \
|
||||
+ options_list + [self.download_item_obj.media_data_obj.source]
|
||||
cmd_list = [app_obj.ytdl_path] + options_list + [media_data_obj.source]
|
||||
|
||||
return cmd_list
|
||||
|
||||
@ -2478,7 +2633,8 @@ class VideoDownloader(object):
|
||||
|
||||
def stop(self):
|
||||
|
||||
"""Called by downloads.DownloadWorker.close().
|
||||
"""Called by downloads.DownloadWorker.close() and also by
|
||||
mainwin.MainWin.on_progress_list_stop_now().
|
||||
|
||||
Terminates the child process and sets this object's return code to
|
||||
self.STOPPED.
|
||||
@ -2505,6 +2661,21 @@ class VideoDownloader(object):
|
||||
self.set_return_code(self.STOPPED)
|
||||
|
||||
|
||||
def stop_soon(self):
|
||||
|
||||
"""Can be called by anything. Currently called by
|
||||
mainwin.MainWin.on_progress_list_stop_soon().
|
||||
|
||||
Sets the flag that causes this VideoDownloader to stop after the
|
||||
current video.
|
||||
"""
|
||||
|
||||
if DEBUG_FUNC_FLAG:
|
||||
print('dl 2224 stop_soon')
|
||||
|
||||
self.stop_soon_flag = True
|
||||
|
||||
|
||||
class PipeReader(threading.Thread):
|
||||
|
||||
"""Called by downloads.VideoDownloader.__init__().
|
||||
|
@ -457,15 +457,19 @@ SMALL_ICON_DICT = {
|
||||
'playlist_small': 'playlist.png',
|
||||
'folder_small': 'folder.png',
|
||||
|
||||
'download_small': 'download.png',
|
||||
'archived_small': 'archived.png',
|
||||
'check_small': 'check.png',
|
||||
'download_small': 'download.png',
|
||||
'error_small': 'error.png',
|
||||
'folder_black_small': 'folder_black.png',
|
||||
'folder_blue_small': 'folder_blue.png',
|
||||
'folder_green_small': 'folder_green.png',
|
||||
'folder_red_small': 'folder_red.png',
|
||||
'have_file_small': 'have_file.png',
|
||||
'no_file_small': 'no_file.png',
|
||||
'ok_small': 'ok.png',
|
||||
'error_small': 'error.png',
|
||||
'warning_small': 'warning.png',
|
||||
'system_error_small': 'system_error.png',
|
||||
'system_warning_small': 'system_warning.png',
|
||||
'warning_small': 'warning.png',
|
||||
}
|
||||
|
||||
WIN_ICON_LIST = [
|
||||
|
File diff suppressed because it is too large
Load Diff
2467
tartube/mainwin.py
2467
tartube/mainwin.py
File diff suppressed because it is too large
Load Diff
121
tartube/media.py
121
tartube/media.py
@ -541,6 +541,14 @@ class GenericContainer(GenericMedia):
|
||||
# Set accessors
|
||||
|
||||
|
||||
def set_dl_disable_flag(self, flag):
|
||||
|
||||
if flag:
|
||||
self.dl_disable_flag = True
|
||||
else:
|
||||
self.dl_disable_flag = False
|
||||
|
||||
|
||||
def reset_counts(self, vid_count, new_count, fav_count, dl_count):
|
||||
|
||||
"""Called by mainapp.TartubeApp.update_db().
|
||||
@ -588,6 +596,56 @@ class GenericContainer(GenericMedia):
|
||||
self.new_count -= 1
|
||||
|
||||
|
||||
def set_master_dbid(self, app_obj, dbid):
|
||||
|
||||
if dbid == self.master_dbid:
|
||||
# No change to the current value
|
||||
return
|
||||
|
||||
else:
|
||||
|
||||
# Update the old alternative download destination
|
||||
if self.master_dbid != self.dbid:
|
||||
old_dest_obj = app_obj.media_reg_dict[self.master_dbid]
|
||||
old_dest_obj.del_slave_dbid(self.dbid)
|
||||
|
||||
# Update this object's IV
|
||||
self.master_dbid = dbid
|
||||
|
||||
if self.master_dbid != self.dbid:
|
||||
|
||||
# Update the new alternative download destination
|
||||
new_dest_obj = app_obj.media_reg_dict[self.master_dbid]
|
||||
new_dest_obj.add_slave_dbid(self.dbid)
|
||||
|
||||
|
||||
def add_slave_dbid(self, dbid):
|
||||
|
||||
"""Called by self.set_master_dbid() only."""
|
||||
|
||||
# (Failsafe: don't add the same value to self.slave_dbid_list)
|
||||
match_flag = False
|
||||
for slave_dbid in self.slave_dbid_list:
|
||||
if slave_dbid == dbid:
|
||||
match_flag = True
|
||||
break
|
||||
|
||||
if not match_flag:
|
||||
self.slave_dbid_list.append(dbid)
|
||||
|
||||
|
||||
def del_slave_dbid(self, dbid):
|
||||
|
||||
"""Called by self.set_master_dbid() only."""
|
||||
new_list = []
|
||||
|
||||
for slave_dbid in self.slave_dbid_list:
|
||||
if slave_dbid != dbid:
|
||||
new_list.append(slave_dbid)
|
||||
|
||||
self.slave_dbid_list = new_list.copy()
|
||||
|
||||
|
||||
def set_name(self, name):
|
||||
|
||||
"""Must only be called by mainapp.TartubeApp.rename_container()."""
|
||||
@ -905,6 +963,9 @@ class Video(GenericMedia):
|
||||
# it's marked as a favourite if the same IV in the parent channel,
|
||||
# playlist or folder (also in the parent's parent, and so on) is True
|
||||
self.fav_flag = False
|
||||
# Flag set to True if the video is archived, meaning that it can't be
|
||||
# auto-deleted (but it can still be deleted manually by the user)
|
||||
self.archive_flag = False
|
||||
|
||||
# The file's directory, name and extension
|
||||
self.file_dir = None
|
||||
@ -1019,6 +1080,13 @@ class Video(GenericMedia):
|
||||
|
||||
# Set accessors
|
||||
|
||||
def set_archive_flag(self, flag):
|
||||
|
||||
if flag:
|
||||
self.archive_flag = True
|
||||
else:
|
||||
self.archive_flag = False
|
||||
|
||||
|
||||
def set_dl_flag(self, flag=False):
|
||||
|
||||
@ -1303,10 +1371,27 @@ class Channel(GenericRemoteContainer):
|
||||
# Download source (a URL)
|
||||
self.source = None
|
||||
|
||||
# Alternative download destination - the dbid of a channel, playlist or
|
||||
# folder in whose directory videos, thumbnails (etc) are downloaded.
|
||||
# By default, set to the dbid of this channel; but can be set to the
|
||||
# dbid of any other channel/playlist/folder
|
||||
# Used for: (1) adding a channel and its playlists to the Tartube
|
||||
# database, so that duplicate videos don't exist on the user's
|
||||
# filesystem, (2) tying together, for example, a YouTube and a
|
||||
# BitChute account, so that duplicate videos don't exist on the
|
||||
# user's filesystem
|
||||
self.master_dbid = dbid
|
||||
# A list of dbids for any channel, playlist or folder that uses this
|
||||
# channel as its alternative destination
|
||||
self.slave_dbid_list = []
|
||||
|
||||
# Flag set to True if Tartube should always simulate the download of
|
||||
# videos in this channel, or False if the downloads.DownloadManager
|
||||
# object should decide whether to simulate, or not
|
||||
self.dl_sim_flag = False
|
||||
# Flag set to True if this channel should never be checked or
|
||||
# downloaded
|
||||
self.dl_disable_flag = False
|
||||
# Flag set to True if this channel is marked as favourite, meaning
|
||||
# that all child video objects are automatically marked as
|
||||
# favourites
|
||||
@ -1440,10 +1525,27 @@ class Playlist(GenericRemoteContainer):
|
||||
# Download source (a URL)
|
||||
self.source = None
|
||||
|
||||
# Alternative download destination - the dbid of a channel, playlist or
|
||||
# folder in whose directory videos, thumbnails (etc) are downloaded.
|
||||
# By default, set to the dbid of this playlist; but can be set to the
|
||||
# dbid of any other channel/playlist/folder
|
||||
# Used for: (1) adding a channel and its playlists to the Tartube
|
||||
# database, so that duplicate videos don't exist on the user's
|
||||
# filesystem, (2) tying together, for example, a YouTube and a
|
||||
# BitChute account, so that duplicate videos don't exist on the
|
||||
# user's filesystem
|
||||
self.master_dbid = dbid
|
||||
# A list of dbids for any channel, playlist or folder that uses this
|
||||
# playlist as its alternative destination
|
||||
self.slave_dbid_list = []
|
||||
|
||||
# Flag set to True if Tartube should always simulate the download of
|
||||
# videos in this playlist, or False if the downloads.DownloadManager
|
||||
# object should decide whether to simulate, or not
|
||||
self.dl_sim_flag = False
|
||||
# Flag set to True if this playlist should never be checked or
|
||||
# downloaded
|
||||
self.dl_disable_flag = False
|
||||
# Flag set to True if this playlist is marked as favourite, meaning
|
||||
# that all child video objects are automatically marked as
|
||||
# favourites
|
||||
@ -1592,6 +1694,21 @@ class Folder(GenericContainer):
|
||||
# folder can't be changed
|
||||
self.nickname = name
|
||||
|
||||
# Alternative download destination - the dbid of a channel, playlist or
|
||||
# folder in whose directory videos, thumbnails (etc) are downloaded.
|
||||
# By default, set to the dbid of this folder; but can be set to the
|
||||
# dbid of any other channel/playlist/folder
|
||||
# Used for: (1) adding a channel and its playlists to the Tartube
|
||||
# database, so that duplicate videos don't exist on the user's
|
||||
# filesystem, (2) tying together, for example, a YouTube and a
|
||||
# BitChute account, so that duplicate videos don't exist on the
|
||||
# user's filesystem
|
||||
# NB Fixed folders cannot have an alternative download destination
|
||||
self.master_dbid = dbid
|
||||
# A list of dbids for any channel, playlist or folder that uses this
|
||||
# folder as its alternative destination
|
||||
self.slave_dbid_list = []
|
||||
|
||||
# Flag set to False if the folder can be deleted by the user, or True
|
||||
# if it can't be deleted by the user
|
||||
self.fixed_flag = fixed_flag
|
||||
@ -1611,6 +1728,10 @@ class Folder(GenericContainer):
|
||||
# videos in this folder, or False if the downloads.DownloadManager
|
||||
# object should decide whether to simulate, or not
|
||||
self.dl_sim_flag = False
|
||||
# Flag set to True if this folder should never be checked or
|
||||
# downloaded. If True, the setting applies to any descendant
|
||||
# channels, playlists and folders
|
||||
self.dl_disable_flag = False
|
||||
# Flag set to True if this folder is hidden (not visible in the Video
|
||||
# Index). Note that only folders can be hidden; channels and
|
||||
# playlists cannot
|
||||
|
@ -268,6 +268,13 @@ class OptionsManager(object):
|
||||
temporary directories.
|
||||
|
||||
The same applies to the JSON and thumbnail files.
|
||||
|
||||
use_fixed_folder (str or None): If not None, then all videos are
|
||||
downloaded to one of Tartube's fixed folders (not including private
|
||||
folders) - currently, that group consists of only 'Temporary
|
||||
Videos' and 'Unsorted Videos'. The value should match the name of
|
||||
the folder
|
||||
|
||||
"""
|
||||
|
||||
|
||||
@ -371,6 +378,7 @@ class OptionsManager(object):
|
||||
'sim_keep_description': False,
|
||||
'sim_keep_info': False,
|
||||
'sim_keep_thumbnail': True,
|
||||
'use_fixed_folder': None,
|
||||
}
|
||||
|
||||
|
||||
@ -518,6 +526,7 @@ class OptionsParser(object):
|
||||
# OptionHolder('sim_keep_description', '', False),
|
||||
# OptionHolder('sim_keep_info', '', False),
|
||||
# OptionHolder('sim_keep_thumbnail', '', False),
|
||||
# OptionHolder('use_fixed_folder', '', None),
|
||||
]
|
||||
|
||||
|
||||
@ -721,16 +730,31 @@ class OptionsParser(object):
|
||||
"""
|
||||
|
||||
# Set the directory in which any downloaded videos will be saved
|
||||
app_obj = self.download_manager_obj.app_obj
|
||||
media_data_obj = download_item_obj.media_data_obj
|
||||
if isinstance(media_data_obj, media.Video):
|
||||
save_path = media_data_obj.parent_obj.get_dir(
|
||||
self.download_manager_obj.app_obj
|
||||
)
|
||||
override_name = copy_dict['use_fixed_folder']
|
||||
|
||||
if not isinstance(media_data_obj, media.Video) \
|
||||
and override_name is not None \
|
||||
and override_name in app_obj.media_name_dict:
|
||||
|
||||
# Because of the override, save all videos to a fixed folder
|
||||
other_dbid = app_obj.media_name_dict[override_name]
|
||||
other_obj = app_obj.media_reg_dict[other_dbid]
|
||||
save_path = other_obj.get_dir(app_obj)
|
||||
|
||||
else:
|
||||
save_path = media_data_obj.get_dir(
|
||||
self.download_manager_obj.app_obj
|
||||
)
|
||||
|
||||
if isinstance(media_data_obj, media.Video):
|
||||
save_path = media_data_obj.parent_obj.get_dir(
|
||||
self.download_manager_obj.app_obj
|
||||
)
|
||||
|
||||
else:
|
||||
save_path = media_data_obj.get_dir(
|
||||
self.download_manager_obj.app_obj
|
||||
)
|
||||
|
||||
|
||||
# Set the youtube-dl output template for the video's file
|
||||
template = formats.FILE_OUTPUT_CONVERT_DICT[copy_dict['output_format']]
|
||||
|
@ -35,8 +35,8 @@ import mainapp
|
||||
|
||||
# 'Global' variables
|
||||
__packagename__ = 'tartube'
|
||||
__version__ = '1.1.015'
|
||||
__date__ = '22 Aug 2019'
|
||||
__version__ = '1.1.050'
|
||||
__date__ = '26 Aug 2019'
|
||||
__copyright__ = 'Copyright \xa9 2019 A S Lewis'
|
||||
__license__ = """
|
||||
Copyright \xc2\xa9 2019 A S Lewis.
|
||||
@ -64,7 +64,7 @@ __app_id__ = 'io.sourceforge.tartube'
|
||||
# This is the default executable, in which youtube-dl updates are enabled. For
|
||||
# Debian packaging, use the 'tartube_debian' executable (see the comments in
|
||||
# setup.py)
|
||||
__disable_ytdl_update_flag__ = False
|
||||
__debian_install_flag__ = False
|
||||
# Tartube's icons are stored in the ../icons directory. If packagers want to
|
||||
# move them somewhere else, then adding the directory path to this list will
|
||||
# tell mainwin.MainWin.setup_pixbufs() how to find them
|
||||
|
@ -35,8 +35,8 @@ import mainapp
|
||||
|
||||
# 'Global' variables
|
||||
__packagename__ = 'tartube'
|
||||
__version__ = '1.1.015'
|
||||
__date__ = '22 Aug 2019'
|
||||
__version__ = '1.1.050'
|
||||
__date__ = '26 Aug 2019'
|
||||
__copyright__ = 'Copyright \xa9 2019 A S Lewis'
|
||||
__license__ = """
|
||||
Copyright \xc2\xa9 2019 A S Lewis.
|
||||
@ -64,7 +64,7 @@ __app_id__ = 'io.sourceforge.tartube'
|
||||
# This is a modified executable, in which youtube-dl updates are disabled
|
||||
# (to meet the demands of Debian packaging). All other users should run the
|
||||
# 'tartube' executable (see the comments in setup.py)
|
||||
__disable_ytdl_update_flag__ = True
|
||||
__debian_install_flag__ = True
|
||||
# Tartube's icons are stored in the ../icons directory. If packagers want to
|
||||
# move them somewhere else, then adding the directory path to this list will
|
||||
# tell mainwin.MainWin.setup_pixbufs() how to find them
|
||||
|
Loading…
x
Reference in New Issue
Block a user