Update to v1.3.007
16
CHANGES
@ -1,4 +1,18 @@
|
||||
v1.3.0 (20 Sep 2019)
|
||||
v1.3.007 (20 Dec 2019)
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
MAJOR FIXES
|
||||
- v1.3.007 was completely broken when replacing an earlier installation. Fixed
|
||||
- When Tartube's data directory was copied from one place to another (for
|
||||
example, from one external drive to another), Tartube did not adapt to the
|
||||
change very well. The way file paths are stored in Tartube's database has
|
||||
been changed to eliminate this problem
|
||||
|
||||
MINOR FIXES
|
||||
- Fixed an invalid time value which (sometimes) prevented a refresh operation
|
||||
from completing correctly
|
||||
|
||||
v1.3.0 (20 Dec 2019)
|
||||
-------------------------------------------------------------------------------
|
||||
MAJOR NEW FEATURES
|
||||
- Tartube on MS Windows did not recognise FFmpeg or AVConv. You can now tell
|
||||
|
39
README.rst
@ -11,40 +11,9 @@ Works with YouTube, BitChute, and hundreds of other websites
|
||||
* `1 Introduction`_
|
||||
* `2 Why should I use Tartube?`_
|
||||
* `3 Quick start guide`_
|
||||
* `3.1 MS Windows`_
|
||||
* `3.2 Linux/BSD`_
|
||||
* `4 Downloads`_
|
||||
* `5 Installation`_
|
||||
* `5.1 Installation - MS Windows`_
|
||||
* `5.2 Installation - MacOS`_
|
||||
* `5.3 Installation - Linux/BSD`_
|
||||
* `5.3.1 Linux/BSD Installation requirements`_
|
||||
* `5.3.2 Optional dependencies`_
|
||||
* `5.3.3 Install using PyPI`_
|
||||
* `5.3.4 Install from source`_
|
||||
* `5.3.5 Run without installing`_
|
||||
* `6 Getting started`_
|
||||
* `6.1 Choose where to save videos`_
|
||||
* `6.2 Check youtube-dl is updated`_
|
||||
* `6.3 Setting youtube-dl's location`_
|
||||
* `6.4 Setting the location of FFmpeg / AVConv`_
|
||||
* `6.4.1 On MS Windows`_
|
||||
* `6.4.2 On Linux/BSD`_
|
||||
* `6.5 Introducing system folders`_
|
||||
* `6.6 Adding videos`_
|
||||
* `6.7 Adding channels and playlists`_
|
||||
* `6.8 Adding folders`_
|
||||
* `6.9 Things you can do`_
|
||||
* `6.10 General download options`_
|
||||
* `6.11 Other download options`_
|
||||
* `6.12 Favourite videos`_
|
||||
* `6.13 Watching videos`_
|
||||
* `6.14 Combining channels, playlists and folders`_
|
||||
* `6.14.1 Combining one channel and many playlists`_
|
||||
* `6.14.2 Combining channels from different websites`_
|
||||
* `6.14.3 Download all videos to a single folder`_
|
||||
* `6.15 Archiving videos`_
|
||||
* `6.16 Exporting/importing the Tartube database`_
|
||||
* `7. Frequently-Asked Questions`_
|
||||
* `8. Future plans`_
|
||||
* `9. Known issues`_
|
||||
@ -110,11 +79,11 @@ Problems can be reported at `our GitHub page <https://github.com/axcore/tartube/
|
||||
4 Downloads
|
||||
===========
|
||||
|
||||
Latest version: **v1.3.0 (20 Dec 2019)**
|
||||
Latest version: **v1.3.007 (20 Dec 2019)**
|
||||
|
||||
- `MS Windows (32-bit) installer <https://sourceforge.net/projects/tartube/files/v1.3.0/install-tartube-1.3.0-32bit.exe/download>`__ from Sourceforge
|
||||
- `MS Windows (64-bit) installer <https://sourceforge.net/projects/tartube/files/v1.3.0/install-tartube-1.3.0-64bit.exe/download>`__ from Sourceforge
|
||||
- `Source code <https://sourceforge.net/projects/tartube/files/v1.3.0/tartube_v1.3.0.tar.gz/download>`__ from Sourceforge
|
||||
- `MS Windows (32-bit) installer <https://sourceforge.net/projects/tartube/files/v1.3.007/install-tartube-1.3.007-32bit.exe/download>`__ from Sourceforge
|
||||
- `MS Windows (64-bit) installer <https://sourceforge.net/projects/tartube/files/v1.3.007/install-tartube-1.3.007-64bit.exe/download>`__ from Sourceforge
|
||||
- `Source code <https://sourceforge.net/projects/tartube/files/v1.3.007/tartube_v1.3.007.tar.gz/download>`__ from Sourceforge
|
||||
- `Source code <https://github.com/axcore/tartube>`__ and `support <https://github.com/axcore/tartube/issues>`__ from GitHub
|
||||
|
||||
5 Installation
|
||||
|
@ -5,13 +5,14 @@ All files in the ../win sub-directory
|
||||
|
||||
Author: Vectorgraphit
|
||||
Source: https://www.iconfinder.com/icons/199499/
|
||||
Author: bekeen studio
|
||||
https://www.iconfinder.com/bekeenstudio
|
||||
|
||||
This work is licensed under the Creative Commons Attribution 3.0 Unported
|
||||
License. To view a copy of this license, visit
|
||||
http://creativecommons.org/licenses/by/3.0/ or send a letter to Creative
|
||||
Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.
|
||||
|
||||
|
||||
All files in the ../large sub-directory
|
||||
All files in the ../small sub-directory
|
||||
All files in the ../template sub-directory
|
||||
|
BIN
icons/dialogue/system_icon_xmas_64.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
icons/win/system_icon_xmas_128.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
icons/win/system_icon_xmas_16.png
Normal file
After Width: | Height: | Size: 895 B |
BIN
icons/win/system_icon_xmas_24.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
icons/win/system_icon_xmas_256.png
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
icons/win/system_icon_xmas_32.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
icons/win/system_icon_xmas_48.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
icons/win/system_icon_xmas_512.png
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
icons/win/system_icon_xmas_64.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
@ -1,4 +1,4 @@
|
||||
# Tartube v1.3.0 installer script for MS Windows
|
||||
# Tartube v1.3.007 installer script for MS Windows
|
||||
#
|
||||
# Copyright (C) 2019 A S Lewis
|
||||
#
|
||||
@ -139,7 +139,7 @@
|
||||
|
||||
;Name and file
|
||||
Name "Tartube"
|
||||
OutFile "install-tartube-1.3.0-32bit.exe"
|
||||
OutFile "install-tartube-1.3.007-32bit.exe"
|
||||
|
||||
;Default installation folder
|
||||
InstallDir "$LOCALAPPDATA\Tartube"
|
||||
@ -244,7 +244,7 @@ Section "Tartube" SecClient
|
||||
"Publisher" "A S Lewis"
|
||||
WriteRegStr HKLM \
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\Tartube" \
|
||||
"DisplayVersion" "1.3.0"
|
||||
"DisplayVersion" "1.3.007"
|
||||
|
||||
# Create uninstaller
|
||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Tartube v1.3.0 installer script for MS Windows
|
||||
# Tartube v1.3.007 installer script for MS Windows
|
||||
#
|
||||
# Copyright (C) 2019 A S Lewis
|
||||
#
|
||||
@ -140,7 +140,7 @@
|
||||
|
||||
;Name and file
|
||||
Name "Tartube"
|
||||
OutFile "install-tartube-1.3.0-64bit.exe"
|
||||
OutFile "install-tartube-1.3.007-64bit.exe"
|
||||
|
||||
;Default installation folder
|
||||
InstallDir "$LOCALAPPDATA\Tartube"
|
||||
@ -245,7 +245,7 @@ Section "Tartube" SecClient
|
||||
"Publisher" "A S Lewis"
|
||||
WriteRegStr HKLM \
|
||||
"Software\Microsoft\Windows\CurrentVersion\Uninstall\Tartube" \
|
||||
"DisplayVersion" "1.3.0"
|
||||
"DisplayVersion" "1.3.007"
|
||||
|
||||
# Create uninstaller
|
||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||
|
2
setup.py
@ -62,7 +62,7 @@ if env_var_value is not None:
|
||||
# Setup
|
||||
setuptools.setup(
|
||||
name='tartube',
|
||||
version='1.3.0',
|
||||
version='1.3.007',
|
||||
description='GUI front-end for youtube-dl',
|
||||
# long_description=long_description,
|
||||
long_description="""Tartube is a GUI front-end for youtube-dl, partly based
|
||||
|
@ -4096,6 +4096,7 @@ class VideoEditWin(GenericEditWin):
|
||||
entry6.set_text(
|
||||
os.path.abspath(
|
||||
os.path.join(
|
||||
self.app_obj.downloads_dir,
|
||||
self.edit_obj.file_dir,
|
||||
self.edit_obj.file_name + self.edit_obj.file_ext,
|
||||
),
|
||||
|
@ -1982,7 +1982,7 @@ class VideoDownloader(object):
|
||||
# If the 'Add videos' button was used, the path/filename/extension
|
||||
# won't be set yet
|
||||
if not video_obj.file_dir and full_path:
|
||||
video_obj.set_file(path, filename, extension)
|
||||
video_obj.set_file(filename, extension)
|
||||
|
||||
# Update any video object IVs that are not set
|
||||
if video_obj.name == app_obj.default_video_name \
|
||||
@ -2084,6 +2084,7 @@ class VideoDownloader(object):
|
||||
# thumbnail locally
|
||||
thumb_path = os.path.abspath(
|
||||
os.path.join(
|
||||
app_obj.downloads_dir,
|
||||
video_obj.file_dir,
|
||||
video_obj.file_name + remote_ext,
|
||||
),
|
||||
|
@ -25,13 +25,22 @@
|
||||
|
||||
|
||||
# Import other modules
|
||||
# ...
|
||||
import datetime
|
||||
|
||||
|
||||
# Import our modules
|
||||
# ...
|
||||
|
||||
|
||||
# Some icons are different at Christmas
|
||||
today = datetime.date.today()
|
||||
day = today.strftime("%d")
|
||||
month = today.strftime("%m")
|
||||
if (int(month) == 12 and int(day) >= 24) or (int(month) == 1 and int(day) <= 5):
|
||||
xmas_flag = True
|
||||
else:
|
||||
xmas_flag = False
|
||||
|
||||
# Used by utils.format_bytes()
|
||||
KILO_SIZE = 1024.0
|
||||
FILESIZE_METRIC_LIST = [
|
||||
@ -417,9 +426,14 @@ LANGUAGE_CODE_LIST = [
|
||||
['Zulu', 'zu'],
|
||||
]
|
||||
|
||||
DIALOGUE_ICON_DICT = {
|
||||
'system_icon': 'system_icon_64.png',
|
||||
}
|
||||
if not xmas_flag:
|
||||
DIALOGUE_ICON_DICT = {
|
||||
'system_icon': 'system_icon_64.png',
|
||||
}
|
||||
else:
|
||||
DIALOGUE_ICON_DICT = {
|
||||
'system_icon': 'system_icon_xmas_64.png',
|
||||
}
|
||||
|
||||
TOOLBAR_ICON_DICT = {
|
||||
'tool_channel_large': 'channel_large.png',
|
||||
@ -514,13 +528,25 @@ SMALL_ICON_DICT = {
|
||||
'warning_small': 'warning.png',
|
||||
}
|
||||
|
||||
WIN_ICON_LIST = [
|
||||
'system_icon_16.png',
|
||||
'system_icon_24.png',
|
||||
'system_icon_32.png',
|
||||
'system_icon_48.png',
|
||||
'system_icon_64.png',
|
||||
'system_icon_128.png',
|
||||
'system_icon_256.png',
|
||||
'system_icon_512.png',
|
||||
]
|
||||
if not xmas_flag:
|
||||
WIN_ICON_LIST = [
|
||||
'system_icon_16.png',
|
||||
'system_icon_24.png',
|
||||
'system_icon_32.png',
|
||||
'system_icon_48.png',
|
||||
'system_icon_64.png',
|
||||
'system_icon_128.png',
|
||||
'system_icon_256.png',
|
||||
'system_icon_512.png',
|
||||
]
|
||||
else:
|
||||
WIN_ICON_LIST = [
|
||||
'system_icon_xmas_16.png',
|
||||
'system_icon_xmas_24.png',
|
||||
'system_icon_xmas_32.png',
|
||||
'system_icon_xmas_48.png',
|
||||
'system_icon_xmas_64.png',
|
||||
'system_icon_xmas_128.png',
|
||||
'system_icon_xmas_256.png',
|
||||
'system_icon_xmas_512.png',
|
||||
]
|
||||
|
@ -1936,7 +1936,7 @@ class TartubeApp(Gtk.Application):
|
||||
= json_dict['auto_delete_watched_flag']
|
||||
self.auto_delete_days = json_dict['auto_delete_days']
|
||||
|
||||
if version >= 1001041: # v1.1.041
|
||||
if version >= 1002041: # v1.2.041
|
||||
self.delete_on_shutdown_flag = json_dict['delete_on_shutdown_flag']
|
||||
|
||||
self.complex_index_flag = json_dict['complex_index_flag']
|
||||
@ -2339,7 +2339,7 @@ class TartubeApp(Gtk.Application):
|
||||
# To be safe, update every video in the registry
|
||||
for media_data_obj in self.media_reg_dict.values():
|
||||
if isinstance(media_data_obj, media.Video):
|
||||
media_data_obj.reset_file_dir(self)
|
||||
media_data_obj.reset_file_dir()
|
||||
|
||||
if version < 4015: # v0.4.015
|
||||
|
||||
@ -2434,6 +2434,7 @@ class TartubeApp(Gtk.Application):
|
||||
# to set the nickname
|
||||
json_path = os.path.abspath(
|
||||
os.path.join(
|
||||
self.downloads_dir,
|
||||
media_data_obj.file_dir,
|
||||
media_data_obj.file_name + '.info.json',
|
||||
),
|
||||
@ -2550,15 +2551,14 @@ class TartubeApp(Gtk.Application):
|
||||
= options_obj.options_dict['to_audio']
|
||||
options_obj.options_dict.pop('to_audio')
|
||||
|
||||
if version < 1002005: # v1.2.005
|
||||
if version < 1003004: # v1.3.004
|
||||
|
||||
# After moving videos from one filesystem location to another,
|
||||
# some media.Video had the wrong value for their .file_dir IV
|
||||
# To be safe, reset them all
|
||||
# The way that directories are stored in media.VideoObj.file_dir
|
||||
# has changed. Reset those values for all video objects
|
||||
for media_data_obj in self.media_reg_dict.values():
|
||||
if isinstance(media_data_obj, media.Video):
|
||||
|
||||
media_data_obj.reset_file_dir(self)
|
||||
media_data_obj.reset_file_dir()
|
||||
|
||||
|
||||
def save_db(self):
|
||||
@ -3466,10 +3466,16 @@ class TartubeApp(Gtk.Application):
|
||||
|
||||
# Get the time taken by the download operation, so we can convert it
|
||||
# into a nice string below (e.g. '05:15')
|
||||
time_num = int(
|
||||
self.download_manager_obj.stop_time \
|
||||
- self.download_manager_obj.start_time
|
||||
)
|
||||
# For refresh operations, RefreshManager.stop_time() might not have
|
||||
# been set at this point (for some reason), so we need to check for
|
||||
# the equivalent problem
|
||||
if self.download_manager_obj.stop_time is not None:
|
||||
time_num = int(
|
||||
self.download_manager_obj.stop_time \
|
||||
- self.download_manager_obj.start_time
|
||||
)
|
||||
else:
|
||||
time_num = int(time.time() - self.download_manager_obj.start_time)
|
||||
|
||||
# Any code can check whether a download/update/refresh operation is in
|
||||
# progress, or not, by checking this IV
|
||||
@ -3895,10 +3901,15 @@ class TartubeApp(Gtk.Application):
|
||||
|
||||
# Get the time taken by the download operation, so we can convert it
|
||||
# into a nice string below (e.g. '05:15')
|
||||
time_num = int(
|
||||
self.refresh_manager_obj.stop_time \
|
||||
- self.refresh_manager_obj.start_time
|
||||
)
|
||||
# For some reason, RefreshManager.stop_time() might not be set, so we
|
||||
# need to check for that
|
||||
if self.refresh_manager_obj.stop_time is not None:
|
||||
time_num = int(
|
||||
self.refresh_manager_obj.stop_time \
|
||||
- self.refresh_manager_obj.start_time
|
||||
)
|
||||
else:
|
||||
time_num = int(time.time() - self.refresh_manager_obj.start_time)
|
||||
|
||||
# Any code can check whether a download/update/refresh operation is in
|
||||
# progress, or not, by checking this IV
|
||||
@ -3998,7 +4009,7 @@ class TartubeApp(Gtk.Application):
|
||||
# If the video was added manually (for example, using the 'Add
|
||||
# videos' button), then its filepath won't be set yet
|
||||
if not video_obj.file_dir:
|
||||
video_obj.set_file(dir_path, filename, extension)
|
||||
video_obj.set_file(filename, extension)
|
||||
|
||||
else:
|
||||
|
||||
@ -4008,9 +4019,20 @@ class TartubeApp(Gtk.Application):
|
||||
video_obj = None
|
||||
for child_obj in media_data_obj.child_list:
|
||||
|
||||
child_file_dir = None
|
||||
if child_obj.file_dir is not None:
|
||||
child_file_dir = os.path.abspath(
|
||||
os.path.join(
|
||||
self.downloads_dir,
|
||||
child_obj.file_dir,
|
||||
),
|
||||
)
|
||||
|
||||
if isinstance(child_obj, media.Video) \
|
||||
and child_obj.file_dir and child_obj.file_dir == dir_path \
|
||||
and child_obj.file_name and child_obj.file_name == filename:
|
||||
and child_file_dir \
|
||||
and child_file_dir == dir_path \
|
||||
and child_obj.file_name \
|
||||
and child_obj.file_name == filename:
|
||||
video_obj = child_obj
|
||||
|
||||
if video_obj is None:
|
||||
@ -4040,7 +4062,7 @@ class TartubeApp(Gtk.Application):
|
||||
|
||||
# Since we have them to hand, set the video's file path IVs
|
||||
# immediately
|
||||
video_obj.set_file(dir_path, filename, extension)
|
||||
video_obj.set_file(filename, extension)
|
||||
|
||||
# If the video is in a channel or a playlist, assume that youtube-dl is
|
||||
# supplying a list of videos in the order of upload, newest first -
|
||||
@ -4169,6 +4191,7 @@ class TartubeApp(Gtk.Application):
|
||||
|
||||
old_path = os.path.abspath(
|
||||
os.path.join(
|
||||
self.downloads_dir,
|
||||
video_obj.file_dir,
|
||||
video_obj.file_name + '.description',
|
||||
),
|
||||
@ -4185,6 +4208,7 @@ class TartubeApp(Gtk.Application):
|
||||
|
||||
old_path = os.path.abspath(
|
||||
os.path.join(
|
||||
self.downloads_dir,
|
||||
video_obj.file_dir,
|
||||
video_obj.file_name + '.info.json',
|
||||
),
|
||||
@ -4202,6 +4226,7 @@ class TartubeApp(Gtk.Application):
|
||||
|
||||
old_path = os.path.abspath(
|
||||
os.path.join(
|
||||
self.downloads_dir,
|
||||
video_obj.file_dir,
|
||||
video_obj.file_name + '.annotations.xml',
|
||||
),
|
||||
@ -4256,6 +4281,7 @@ class TartubeApp(Gtk.Application):
|
||||
|
||||
video_path = os.path.abspath(
|
||||
os.path.join(
|
||||
self.downloads_dir,
|
||||
video_obj.file_dir,
|
||||
video_obj.file_name + video_obj.file_ext,
|
||||
)
|
||||
@ -4303,6 +4329,7 @@ class TartubeApp(Gtk.Application):
|
||||
|
||||
json_path = os.path.abspath(
|
||||
os.path.join(
|
||||
self.downloads_dir,
|
||||
video_obj.file_dir,
|
||||
video_obj.file_name + '.info.json',
|
||||
),
|
||||
@ -4382,13 +4409,13 @@ class TartubeApp(Gtk.Application):
|
||||
this_thread.daemon = True
|
||||
this_thread.start()
|
||||
this_thread.join(10) # Timeout after 10 seconds
|
||||
if this_thread.is_alive():
|
||||
self.system_error(
|
||||
132,
|
||||
'\'' + video_obj.parent_obj.name + '\': moviepy module' \
|
||||
+ 'failed to fetch duration of video \'' \
|
||||
+ video_obj.name + '\'',
|
||||
)
|
||||
# if this_thread.is_alive():
|
||||
# self.system_error(
|
||||
# 132,
|
||||
# '\'' + video_obj.parent_obj.name + '\': moviepy module' \
|
||||
# + 'failed to fetch duration of video \'' \
|
||||
# + video_obj.name + '\'',
|
||||
# )
|
||||
|
||||
# (Can't set the video source directly)
|
||||
|
||||
@ -4420,8 +4447,16 @@ class TartubeApp(Gtk.Application):
|
||||
if DEBUG_FUNC_FLAG:
|
||||
print('ap 3751 set_duration_from_moviepy')
|
||||
|
||||
clip = moviepy.editor.VideoFileClip(video_path)
|
||||
video_obj.set_duration(clip.duration)
|
||||
try:
|
||||
clip = moviepy.editor.VideoFileClip(video_path)
|
||||
video_obj.set_duration(clip.duration)
|
||||
except:
|
||||
self.system_error(
|
||||
132,
|
||||
'\'' + video_obj.parent_obj.name + '\': moviepy module' \
|
||||
+ 'failed to fetch duration of video \'' \
|
||||
+ video_obj.name + '\'',
|
||||
)
|
||||
|
||||
|
||||
# (Add media data objects)
|
||||
@ -4853,13 +4888,8 @@ class TartubeApp(Gtk.Application):
|
||||
|
||||
# All videos which are descendents of media_data_obj must have their
|
||||
# .file_dir IV updated to the new location
|
||||
# for video_obj in media_data_obj.compile_all_videos( [] ):
|
||||
# video_obj.reset_file_dir(self)
|
||||
# v1.2.006 This has been observed to fail. Don't know why, yet, so
|
||||
# reset the .file_dir IV for all videos, just to be safe
|
||||
for other_obj in self.media_reg_dict.values():
|
||||
if isinstance(other_obj, media.Video):
|
||||
other_obj.reset_file_dir(self)
|
||||
for video_obj in media_data_obj.compile_all_videos( [] ):
|
||||
video_obj.reset_file_dir()
|
||||
|
||||
# Save the database (because, if the user terminates Tartube and then
|
||||
# restarts it, then tries to perform a download operation, a load of
|
||||
@ -5046,13 +5076,8 @@ class TartubeApp(Gtk.Application):
|
||||
|
||||
# All videos which are descendents of dest_obj must have their
|
||||
# .file_dir IV updated to the new location
|
||||
# for video_obj in source_obj.compile_all_videos( [] ):
|
||||
# video_obj.reset_file_dir(self)
|
||||
# v1.2.006 This has been observed to fail. Don't know why, yet, so
|
||||
# reset the .file_dir IV for all videos, just to be safe
|
||||
for other_obj in self.media_reg_dict.values():
|
||||
if isinstance(other_obj, media.Video):
|
||||
other_obj.reset_file_dir(self)
|
||||
for video_obj in source_obj.compile_all_videos( [] ):
|
||||
video_obj.reset_file_dir()
|
||||
|
||||
# Save the database (because, if the user terminates Tartube and then
|
||||
# restarts it, then tries to perform a download operation, a load of
|
||||
@ -5135,6 +5160,7 @@ class TartubeApp(Gtk.Application):
|
||||
|
||||
video_path = os.path.abspath(
|
||||
os.path.join(
|
||||
self.downloads_dir,
|
||||
video_obj.file_dir,
|
||||
video_obj.file_name + video_obj.file_ext,
|
||||
),
|
||||
@ -5151,6 +5177,7 @@ class TartubeApp(Gtk.Application):
|
||||
|
||||
descrip_path = os.path.abspath(
|
||||
os.path.join(
|
||||
self.downloads_dir,
|
||||
video_obj.file_dir,
|
||||
video_obj.file_name + '.description',
|
||||
),
|
||||
@ -5161,6 +5188,7 @@ class TartubeApp(Gtk.Application):
|
||||
|
||||
json_path = os.path.abspath(
|
||||
os.path.join(
|
||||
self.downloads_dir,
|
||||
video_obj.file_dir,
|
||||
video_obj.file_name + '.info.json',
|
||||
),
|
||||
@ -6047,7 +6075,7 @@ class TartubeApp(Gtk.Application):
|
||||
# All videos which are descendents of media_data_obj must have
|
||||
# their .file_dir IV updated to the new location
|
||||
for video_obj in media_data_obj.compile_all_videos( [] ):
|
||||
video_obj.reset_file_dir(self)
|
||||
video_obj.reset_file_dir()
|
||||
|
||||
# Reset the Video Index and the Video Catalogue (this prevents a
|
||||
# lot of problems)
|
||||
@ -6943,6 +6971,7 @@ class TartubeApp(Gtk.Application):
|
||||
|
||||
path = os.path.abspath(
|
||||
os.path.join(
|
||||
self.downloads_dir,
|
||||
video_obj.file_dir,
|
||||
video_obj.file_name + video_obj.file_ext,
|
||||
),
|
||||
|
@ -5357,6 +5357,7 @@ class MainWin(Gtk.ApplicationWindow):
|
||||
# Get the video's full file path now, as we use it several times
|
||||
video_path = os.path.abspath(
|
||||
os.path.join(
|
||||
self.app_obj.downloads_dir,
|
||||
video_obj.file_dir,
|
||||
video_obj.file_name + video_obj.file_ext,
|
||||
),
|
||||
@ -5371,6 +5372,7 @@ class MainWin(Gtk.ApplicationWindow):
|
||||
mkv_flag = True
|
||||
video_path = os.path.abspath(
|
||||
os.path.join(
|
||||
self.app_obj.downloads_dir,
|
||||
video_obj.file_dir,
|
||||
video_obj.file_name + '.mkv',
|
||||
),
|
||||
@ -7527,6 +7529,7 @@ class MainWin(Gtk.ApplicationWindow):
|
||||
|
||||
path = os.path.abspath(
|
||||
os.path.join(
|
||||
self.app_obj.downloads_dir,
|
||||
media_data_obj.file_dir,
|
||||
media_data_obj.file_name + media_data_obj.file_ext,
|
||||
),
|
||||
@ -8610,6 +8613,7 @@ class SimpleCatalogueItem(object):
|
||||
if self.main_win_obj.app_obj.show_tooltips_flag:
|
||||
self.hbox.set_tooltip_text(
|
||||
self.video_obj.fetch_tooltip_text(
|
||||
self.main_win_obj.app_obj,
|
||||
self.main_win_obj.tooltip_max_len,
|
||||
),
|
||||
)
|
||||
@ -9017,6 +9021,7 @@ class ComplexCatalogueItem(object):
|
||||
if self.main_win_obj.app_obj.show_tooltips_flag:
|
||||
self.frame.set_tooltip_text(
|
||||
self.video_obj.fetch_tooltip_text(
|
||||
self.main_win_obj.app_obj,
|
||||
self.main_win_obj.tooltip_max_len,
|
||||
),
|
||||
)
|
||||
|
@ -716,10 +716,10 @@ class GenericContainer(GenericMedia):
|
||||
|
||||
def get_dir(self, app_obj, new_name=None):
|
||||
|
||||
"""Called by self.__init___(), or any other code.
|
||||
"""Can be called by anything.
|
||||
|
||||
Fetches the full path to the sub-directory used by this channel,
|
||||
playlist or folder.
|
||||
Fetches the full path to the sub-directory currently used by this
|
||||
channel, playlist or folder.
|
||||
|
||||
Args:
|
||||
|
||||
@ -752,6 +752,41 @@ class GenericContainer(GenericMedia):
|
||||
return os.path.abspath(os.path.join(app_obj.downloads_dir, *dir_list))
|
||||
|
||||
|
||||
def get_relative_dir(self, new_name=None):
|
||||
|
||||
"""Can be called by anything, for example by media.VideoObj.set_file().
|
||||
|
||||
Fetches the path to the sub-directory used by this channel, playlist or
|
||||
folder, relative to mainapp.TartubeApp.downloads_dir.
|
||||
|
||||
Args:
|
||||
|
||||
new_name (str): If specified, fetches the relative path to the
|
||||
sub-directory that would be used by this channel, playlist or
|
||||
folder, if it were renamed to 'new_name'. If not specified, the
|
||||
channel/playlist/folder's actual name is used
|
||||
|
||||
Returns:
|
||||
|
||||
The path to the directory relative to
|
||||
mainapp.TartubeApp.downloads_dir
|
||||
|
||||
"""
|
||||
|
||||
if new_name is not None:
|
||||
dir_list = [new_name]
|
||||
else:
|
||||
dir_list = [self.name]
|
||||
|
||||
obj = self
|
||||
while obj.parent_obj:
|
||||
|
||||
obj = obj.parent_obj
|
||||
dir_list.insert(0, obj.name)
|
||||
|
||||
return os.path.join(*dir_list)
|
||||
|
||||
|
||||
class GenericRemoteContainer(GenericContainer):
|
||||
|
||||
"""Base python class inherited by media.Channel and media.Playlist."""
|
||||
@ -1015,7 +1050,8 @@ class Video(GenericMedia):
|
||||
# auto-deleted (but it can still be deleted manually by the user)
|
||||
self.archive_flag = False
|
||||
|
||||
# The file's directory, name and extension
|
||||
# The file's directory (relative to mainapp.TartubeApp.downloads_dir),
|
||||
# name and extension
|
||||
self.file_dir = None
|
||||
self.file_name = None
|
||||
self.file_ext = None
|
||||
@ -1099,13 +1135,15 @@ class Video(GenericMedia):
|
||||
return False
|
||||
|
||||
|
||||
def fetch_tooltip_text(self, max_length=None):
|
||||
def fetch_tooltip_text(self, app_obj, max_length=None):
|
||||
|
||||
"""Called by mainwin.SimpleCatalogueItem.update_tooltips() and
|
||||
mainwin.ComplexCatalogueItem.update_tooltips().
|
||||
|
||||
Args:
|
||||
|
||||
app_obj (mainapp.TartubeApp): The main application
|
||||
|
||||
max_length (int or None): If specified, the maximum line length, in
|
||||
characters
|
||||
|
||||
@ -1130,6 +1168,7 @@ class Video(GenericMedia):
|
||||
else:
|
||||
text += os.path.abspath(
|
||||
os.path.join(
|
||||
app_obj.downloads_dir,
|
||||
self.file_dir,
|
||||
self.file_name + self.file_ext,
|
||||
),
|
||||
@ -1140,7 +1179,6 @@ class Video(GenericMedia):
|
||||
|
||||
# Apply a maximum line length, if required
|
||||
if max_length is not None:
|
||||
# text = utils.tidy_up_long_string(text, max_length, False)
|
||||
text = utils.tidy_up_long_descrip(text, max_length)
|
||||
|
||||
return text
|
||||
@ -1163,6 +1201,7 @@ class Video(GenericMedia):
|
||||
|
||||
descrip_path = os.path.abspath(
|
||||
os.path.join(
|
||||
app_obj.downloads_dir,
|
||||
self.file_dir,
|
||||
self.file_name + '.description',
|
||||
),
|
||||
@ -1206,14 +1245,14 @@ class Video(GenericMedia):
|
||||
self.duration = None
|
||||
|
||||
|
||||
def set_file(self, path, filename, extension):
|
||||
def set_file(self, filename, extension):
|
||||
|
||||
self.file_dir = path
|
||||
self.file_dir = self.parent_obj.get_relative_dir()
|
||||
self.file_name = filename
|
||||
self.file_ext = extension
|
||||
|
||||
|
||||
def reset_file_dir(self, app_obj):
|
||||
def reset_file_dir(self):
|
||||
|
||||
"""Called by mainapp.TartubeApp.move_container_to_top_continue()
|
||||
and .move_container_continue().
|
||||
@ -1223,7 +1262,7 @@ class Video(GenericMedia):
|
||||
moved along with it must have its .file_dir IV updated.
|
||||
"""
|
||||
|
||||
self.file_dir = self.parent_obj.get_dir(app_obj)
|
||||
self.file_dir = self.parent_obj.get_relative_dir()
|
||||
|
||||
|
||||
def set_file_size(self, size=None):
|
||||
|
@ -335,7 +335,7 @@ class RefreshManager(threading.Thread):
|
||||
= child_obj.file_name + child_obj.file_ext
|
||||
|
||||
if not child_relative_path in alt_list:
|
||||
child_obj.set_file(dir_path, filename, ext)
|
||||
child_obj.set_file(filename, ext)
|
||||
|
||||
# Eliminate this media.Video object; no other video file should
|
||||
# match it
|
||||
@ -378,7 +378,8 @@ class RefreshManager(threading.Thread):
|
||||
# Set the new video object's IVs
|
||||
filename, ext = os.path.splitext(filter_dict[filename])
|
||||
video_obj.set_name(filename)
|
||||
video_obj.set_file(dir_path, filename, ext)
|
||||
video_obj.set_nickname(filename)
|
||||
video_obj.set_file(filename, ext)
|
||||
|
||||
if ext == '.mkv':
|
||||
video_obj.set_mkv()
|
||||
|
@ -35,7 +35,7 @@ import mainapp
|
||||
|
||||
# 'Global' variables
|
||||
__packagename__ = 'tartube'
|
||||
__version__ = '1.3.0'
|
||||
__version__ = '1.3.007'
|
||||
__date__ = '20 Dec 2019'
|
||||
__copyright__ = 'Copyright \xa9 2019 A S Lewis'
|
||||
__license__ = """
|
||||
|
@ -35,7 +35,7 @@ import mainapp
|
||||
|
||||
# 'Global' variables
|
||||
__packagename__ = 'tartube'
|
||||
__version__ = '1.3.0'
|
||||
__version__ = '1.3.007'
|
||||
__date__ = '20 Dec 2019'
|
||||
__copyright__ = 'Copyright \xa9 2019 A S Lewis'
|
||||
__license__ = """
|
||||
|
@ -401,6 +401,7 @@ def find_thumbnail(app_obj, video_obj, temp_dir_flag=False):
|
||||
# Look in main data directory
|
||||
path = os.path.abspath(
|
||||
os.path.join(
|
||||
app_obj.downloads_dir,
|
||||
video_obj.file_dir,
|
||||
video_obj.file_name + ext,
|
||||
),
|
||||
|