Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve handling of big media directories (#694) #699

Merged
merged 3 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 18 additions & 29 deletions syncplay/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@
from syncplay.messages import getMissingStrings, getMessage, isNoOSDMessage
from syncplay.protocols import SyncClientProtocol
from syncplay.utils import isMacOS


class SyncClientFactory(ClientFactory):
def __init__(self, client, retry=constants.RECONNECT_RETRIES):
self._client = client
Expand Down Expand Up @@ -74,6 +72,7 @@ def __init__(self, playerClass, ui, config):
constants.FOLDER_SEARCH_FIRST_FILE_TIMEOUT = config['folderSearchFirstFileTimeout']
constants.FOLDER_SEARCH_TIMEOUT = config['folderSearchTimeout']
constants.FOLDER_SEARCH_DOUBLE_CHECK_INTERVAL = config['folderSearchDoubleCheckInterval']
constants.FOLDER_SEARCH_WARNING_THRESHOLD = config['folderSearchWarningThreshold']

self.controlpasswords = {}
self.lastControlPasswordAttempt = None
Expand Down Expand Up @@ -2197,6 +2196,9 @@ def _updateInfoThread(self):
self.currentlyUpdating = True
dirsToSearch = self.mediaDirectories

if not self.folderSearchEnabled:
return

if dirsToSearch:
# Spin up hard drives to prevent premature timeout
randomFilename = "RandomFile"+str(random.randrange(10000, 99999))+".txt"
Expand All @@ -2216,13 +2218,21 @@ def _updateInfoThread(self):
# Actual directory search
newMediaFilesCache = {}
startTime = time.time()
fileCount = 0
lastWarningTime = None
for directory in dirsToSearch:
for root, dirs, files in os.walk(directory):
fileCount += 1
newMediaFilesCache[root] = files
if time.time() - startTime > constants.FOLDER_SEARCH_TIMEOUT:
self.directorySearchError = getMessage("folder-search-timeout-error").format(directory)
timeTakenSoFar = time.time() - startTime
if timeTakenSoFar > constants.FOLDER_SEARCH_TIMEOUT:
reactor.callLater(0.1, self._client.ui.showErrorMessage, getMessage("folder-search-timeout-error").format(directory, fileCount),False)
self.folderSearchEnabled = False
return
if timeTakenSoFar > constants.FOLDER_SEARCH_WARNING_THRESHOLD:
if not lastWarningTime or timeTakenSoFar - lastWarningTime >= 1:
reactor.callLater(0.1, self._client.ui.showErrorMessage, getMessage("folder-search-timeout-warning").format(int(timeTakenSoFar), fileCount, directory),False)
lastWarningTime = timeTakenSoFar

if self.mediaFilesCache != newMediaFilesCache:
self.mediaFilesCache = newMediaFilesCache
Expand Down Expand Up @@ -2250,33 +2260,12 @@ def findFilepath(self, filename, highPriority=False):
if os.path.isfile(filepath):
return filepath

if highPriority and self.folderSearchEnabled and self.mediaDirectories is not None:
if self.folderSearchEnabled and self.mediaDirectories is not None:
directoryList = self.mediaDirectories
# Spin up hard drives to prevent premature timeout
randomFilename = "RandomFile"+str(random.randrange(10000, 99999))+".txt"
for directory in directoryList:
startTime = time.time()
if os.path.isfile(os.path.join(directory, randomFilename)):
randomFilename = "RandomFile"+str(random.randrange(10000, 99999))+".txt"
print("Found random file (?)")
if not self.folderSearchEnabled:
return
if time.time() - startTime > constants.FOLDER_SEARCH_FIRST_FILE_TIMEOUT:
self.folderSearchEnabled = False
self.directorySearchError = getMessage("folder-search-first-file-timeout-error").format(directory)
return

startTime = time.time()
if filename and directoryList:
for directory in directoryList:
for root, dirs, files in os.walk(directory):
if filename in files:
return os.path.join(root, filename)
if time.time() - startTime > constants.FOLDER_SEARCH_TIMEOUT:
self.folderSearchEnabled = False
self.directorySearchError = getMessage("folder-search-timeout-error").format(directory)
return None
return None
filepath = os.path.join(directory, filename)
if os.path.isfile(filepath):
return filepath

def areWatchedFilenamesInCache(self):
if self.filenameWatchlist is not None:
Expand Down
3 changes: 2 additions & 1 deletion syncplay/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ def getValueForOS(constantDict):
# Options for the File Switch feature:
FOLDER_SEARCH_FIRST_FILE_TIMEOUT = 25.0 # Secs - How long to wait to find the first file in folder search (to take account of HDD spin up)
FOLDER_SEARCH_TIMEOUT = 20.0 # Secs - How long to wait until searches in folder to update cache are aborted (after first file is found)
FOLDER_SEARCH_WARNING_THRESHOLD = 2.0 # Secs - how long until a warning saying how many files have been scanned
FOLDER_SEARCH_DOUBLE_CHECK_INTERVAL = 30.0 # Secs - Frequency of updating cache

# Usually there's no need to adjust these
Expand Down Expand Up @@ -364,4 +365,4 @@ def getValueForOS(constantDict):
CONSOLE_UI_MODE = "CLI"
GRAPHICAL_UI_MODE = "GUI"
UNKNOWN_UI_MODE = "Unknown"
FALLBACK_ASSUMED_UI_MODE = GRAPHICAL_UI_MODE
FALLBACK_ASSUMED_UI_MODE = GRAPHICAL_UI_MODE
3 changes: 2 additions & 1 deletion syncplay/messages_de.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,8 @@
"invalid-offset-value": "Ungültiger Offset-Wert",

"switch-file-not-found-error": "Konnte nicht zur Datei „{0}“ wechseln. Syncplay sucht im Verzeichnis der aktuellen Datei und angegebenen Medienverzeichnissen.", # File not found, folder it was not found in
"folder-search-timeout-error": "Die Suche nach Medien in den Medienverzeichnissen wurde abgebrochen, weil es zu lange gedauert hat, „{}“ zu durchsuchen. Das kann passieren, wenn du in deiner Liste der Medienverzeichnisse ein Verzeichnis mit zu vielen Unterverzeichnissen auswhälst. Damit der automatische Dateiwechsel wieder funktioniert, wähle Datei->Medienverzeichnisse auswählen in der Menüleiste und entferne dieses Verzeichnis oder ersetze es mit einem geeigneten Unterverzeichnis. Wenn das Verzeichnis in Ordnung ist, kannst du es reaktivieren, indem du Datei->Medienverzeichnisse auswählen wählst und „OK“ drückst.", # Folder
"folder-search-timeout-error": "Die Suche nach Medien in den Medienverzeichnissen wurde abgebrochen, weil es zu lange gedauert hat, „{}“ zu durchsuchen (after having processed the first {:,} files). Das kann passieren, wenn du in deiner Liste der Medienverzeichnisse ein Verzeichnis mit zu vielen Unterverzeichnissen auswhälst. Damit der automatische Dateiwechsel wieder funktioniert, wähle Datei->Medienverzeichnisse auswählen in der Menüleiste und entferne dieses Verzeichnis oder ersetze es mit einem geeigneten Unterverzeichnis. Wenn das Verzeichnis in Ordnung ist, kannst du es reaktivieren, indem du Datei->Medienverzeichnisse auswählen wählst und „OK“ drückst.", # Folder, Files processed - Note: {:,} is {} but with added commas seprators - TODO: Translate
"folder-search-timeout-warning": "Warning: It has taken {} seconds to scan {:,} files in the folder '{}'. This will occur if you select a folder with too many sub-folders in your list of media folders to search through or if there are too many files to process.", # Folder, Files processed. Note: {:,} is {} but with added commas seprators. TODO: Translate
"folder-search-first-file-timeout-error": "Die Suche nach Medien in den Medienverzeichnissen wurde abgebrochen, weil es zu lange gedauert hat, auf „{}“ zuzugreifen. Das kann passieren, wenn es sich dabei um ein Netzwerkgerät handelt und du eingestellt hast, dass es sich nach Inaktivität ausschaltet. Damit der automatische Dateiwechsel wieder funktioniert, wähle Datei->Medienverzeichnisse auswählen in der Menüleiste und entferne dieses Verzeichnis oder löse das Problem (z.B. indem du die Energiespareinstellungen anpasst).", # Folder
"added-file-not-in-media-directory-error": "Du hast eine Datei in im Verzeichnis „{}“ geladeden, welches kein bekanntes Medienverzeichnis ist. Du kannst es als Medienverzeichnis hinzufügen, indem du Datei->Medienverzeichnisse auswählen in der Menüleiste wählst.", # Folder
"no-media-directories-error": "Es wurden keine Medienverzeichnisse ausgewählt. Damit geteilte Playlists und Dateiwechsel korrekt funktionieren, wähle Datei->Medienverzeichnisse auswählen in der Menüleiste und gib an, wo Syncplay nach Mediendateien suchen soll.",
Expand Down
3 changes: 2 additions & 1 deletion syncplay/messages_en.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,8 @@
"invalid-offset-value": "Invalid offset value",

"switch-file-not-found-error": "Could not switch to file '{0}'. Syncplay looks in specified media directories.", # File not found
"folder-search-timeout-error": "The search for media in media directories was aborted as it took too long to search through '{}'. This will occur if you select a folder with too many sub-folders in your list of media folders to search through. For automatic file switching to work again please select File->Set Media Directories in the menu bar and remove this directory or replace it with an appropriate sub-folder. If the folder is actually fine then you can re-enable it by selecting File->Set Media Directories and pressing 'OK'.", # Folder
"folder-search-timeout-error": "The search for media in media directories was aborted as it took too long to search through '{}' after having processed the first {:,} files. This will occur if you select a folder with too many sub-folders in your list of media folders to search through or if there are too many files to process. For automatic file switching to work again please select File->Set Media Directories in the menu bar and remove this directory or replace it with an appropriate sub-folder. If the folder is actually fine then you can re-enable it by selecting File->Set Media Directories and pressing 'OK'.", # Folder, Files processed. Note: {:,} is {} but with added commas seprators.
"folder-search-timeout-warning": "Warning: It has taken {} seconds to scan {:,} files in the folder '{}'. This will occur if you select a folder with too many sub-folders in your list of media folders to search through or if there are too many files to process.", # Folder, Files processed. Note: {:,} is {} but with added commas seprators.
"folder-search-first-file-timeout-error": "The search for media in '{}' was aborted as it took too long to access the directory. This could happen if it is a network drive or if you configure your drive to spin down after a period of inactivity. For automatic file switching to work again please go to File->Set Media Directories and either remove the directory or resolve the issue (e.g. by changing power saving settings).", # Folder
"added-file-not-in-media-directory-error": "You loaded a file in '{}' which is not a known media directory. You can add this as a media directory by selecting File->Set Media Directories in the menu bar.", # Folder
"no-media-directories-error": "No media directories have been set. For shared playlist and file switching features to work properly please select File->Set Media Directories and specify where Syncplay should look to find media files.",
Expand Down
3 changes: 2 additions & 1 deletion syncplay/messages_eo.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,8 @@
"invalid-offset-value": "Nevalida valoro de frueco",

"switch-file-not-found-error": "Ne povis ŝalti dosieron «{0}». Syncplay serĉas en donitaj dosierujoj kun vidaŭdaĵoj.", # File not found
"folder-search-timeout-error": "La serĉado de vidaŭdaĵoj en dosierujoj kun vidaŭdaĵoj haltis, ĉar serĉado en «{}» postulis tro da tempo. Ĉi tio okazos, se vi elektos dosierujon kun tro multaj subdosierujoj en via listo de enserĉotaj dosierujoj kun vidaŭdaĵoj. Por refunkciigi memagan ŝaltadon de dosieroj, bonvolu elekti menueron «Dosiero → Agordi dosierujojn kun vidaŭdaĵoj» en la menubreto, kaj forigi ĉi tiun dosierujon, aŭ anstataŭigi ĝin per taŭga sub-dosierujo. Se vi trovos, ke la dosierujo fakte funkcias bone, vi povos reŝalti ĝin per «Dosiero → Agordi dosierujojn kun vidaŭdaĵoj» kaj klako al «Bone».", # Folder
"folder-search-timeout-error": "La serĉado de vidaŭdaĵoj en dosierujoj kun vidaŭdaĵoj haltis, ĉar serĉado en «{}» postulis tro da tempo (after having processed the first {:,} files). Ĉi tio okazos, se vi elektos dosierujon kun tro multaj subdosierujoj en via listo de enserĉotaj dosierujoj kun vidaŭdaĵoj. Por refunkciigi memagan ŝaltadon de dosieroj, bonvolu elekti menueron «Dosiero → Agordi dosierujojn kun vidaŭdaĵoj» en la menubreto, kaj forigi ĉi tiun dosierujon, aŭ anstataŭigi ĝin per taŭga sub-dosierujo. Se vi trovos, ke la dosierujo fakte funkcias bone, vi povos reŝalti ĝin per «Dosiero → Agordi dosierujojn kun vidaŭdaĵoj» kaj klako al «Bone».", # Folder, Files processed - Note: {:,} is {} but with added commas seprators - TODO: Translate
"folder-search-timeout-warning": "Warning: It has taken {} seconds to scan {:,} files in the folder '{}'. This will occur if you select a folder with too many sub-folders in your list of media folders to search through or if there are too many files to process.", # Folder, Files processed. Note: {:,} is {} but with added commas seprators. TODO: Translate
"folder-search-first-file-timeout-error": "La serĉo de vidaŭdaĵoj en «{}» haltis, ĉar aliro al la dosierujo postulis tro da tempo. Ĉi tio povas okazi se ĝi estas reta disko aŭ se vi agordis vian diskon malrapidiĝi post neaktivado. Por ke funkciu memaga ŝanĝado de dosieroj, bonvolu iri al «Dosiero → Agordi vidaŭdaĵajn dosierujojn», kaj forigu la dosierujon, aŭ solvu la problemon (ekz. per ŝanĝo de viaj agordoj por konservado de elektro).", # Folder
"added-file-not-in-media-directory-error": "Vi enlegis dosieron el «{}», kiu ne estas konata vidaŭdaĵa dosierujo. Vi povas aldoni ĝin al vidaŭdaĵaj dosierujoj per la menuero «Dosiero → Agordi vidaŭdaĵajn dosierujojn» en la menua breto.", # Folder
"no-media-directories-error": "Neniuj vidaŭdaĵaj dosierujoj estas agorditaj. Por ke kapabloj de komunaj ludlistoj kaj ŝanĝado de dosieroj funkciu ĝuste, bonvolu elekti menueron «Dosiero → Agordi vidaŭdaĵajn dosierujojn», kaj precizigu, kie Syncplay serĉu vidaŭdaĵojn.",
Expand Down
3 changes: 2 additions & 1 deletion syncplay/messages_es.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,8 @@
"invalid-offset-value": "Valor de desplazamiento inválido",

"switch-file-not-found-error": "No se pudo cambiar el archivo '{0}'. Syncplay busca en los directorios de medios especificados.", # File not found
"folder-search-timeout-error": "Se anuló la búsqueda de medios en el directorio de medios, ya que tardó demasiado buscando en '{}'. Esto ocurrirá si seleccionas una carpeta con demasiadas subcarpetas en tu lista de carpetas de medios para buscar. Para que el cambio automático de archivos vuelva a funcionar, selecciona Archivo->Establecer directorios de medios en la barra de menú y elimina este directorio o reemplázalo con una subcarpeta apropiada. Si la carpeta está bien, puedes volver a reactivarlo seleccionando Archivo->Establecer directorios de medios y presionando 'OK'.", # Folder
"folder-search-timeout-error": "Se anuló la búsqueda de medios en el directorio de medios, ya que tardó demasiado buscando en '{}' (after having processed the first {:,} files). Esto ocurrirá si seleccionas una carpeta con demasiadas subcarpetas en tu lista de carpetas de medios para buscar. Para que el cambio automático de archivos vuelva a funcionar, selecciona Archivo->Establecer directorios de medios en la barra de menú y elimina este directorio o reemplázalo con una subcarpeta apropiada. Si la carpeta está bien, puedes volver a reactivarlo seleccionando Archivo->Establecer directorios de medios y presionando 'OK'.", # Folder, Files processed - Note: {:,} is {} but with added commas seprators - TODO: Translate
"folder-search-timeout-warning": "Warning: It has taken {} seconds to scan {:,} files in the folder '{}'. This will occur if you select a folder with too many sub-folders in your list of media folders to search through or if there are too many files to process.", # Folder, Files processed. Note: {:,} is {} but with added commas seprators. TODO: Translate
"folder-search-first-file-timeout-error": "Se anuló la búsqueda de medios en '{}', ya que tardó demasiado buscando en acceder al directorio. Esto podría ocurrir si se trata de una unidad de red, o si tienes configurada la unidad para centrifugar luego de cierto período de inactividad. Para que el cambio automático de archivos vuelva a funcionar, por favor dirígete a Archivo->Establecer directorios de medios y elimina el directorio o resuelve el problema (p.ej. cambiando la configuración de ahorro de energía).", # Folder
"added-file-not-in-media-directory-error": "Has cargado un archivo en '{}' el cual no es un directorio de medios conocido. Puedes agregarlo como un directorio de medios seleccionado Archivo->Establecer directorios de medios en la barra de menú.", # Folder
"no-media-directories-error": "No se han establecido directorios de medios. Para que las funciones de lista de reproducción compartida y cambio de archivos funcionen correctamente, selecciona Archivo->Establecer directorios de medios y especifica dónde debe buscar Syncplay para encontrar archivos multimedia.",
Expand Down
Loading
Loading