Skip to content

Commit

Permalink
Use filelocks on unix systems
Browse files Browse the repository at this point in the history
  • Loading branch information
7x11x13 committed Jun 23, 2024
1 parent a077939 commit a2c4b50
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 36 deletions.
18 changes: 10 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,31 +55,32 @@ scdl me -f
-r Download all reposts of user
-c Continue if a downloaded file already exists
--force-metadata This will set metadata on already downloaded track
-o [offset] Begin with a custom offset
-o [offset] Start downloading a playlist from the [offset]th track (starting with 1)
--addtimestamp Add track creation timestamp to filename,
which allows for chronological sorting
(Deprecated. Use --name-format instead.)
--addtofile Add artist to filename if missing
--debug Set log level to DEBUG
--error Set log level to ERROR
--download-archive [file] Keep track of track IDs in an archive file,
and skip already-downloaded files
--error Set log level to ERROR
--extract-artist Set artist tag from title instead of username
--hide-progress Hide the wget progress bar
--hidewarnings Hide Warnings. (use with precaution)
--max-size [max-size] Skip tracks larger than size (k/m/g)
--min-size [min-size] Skip tracks smaller than size (k/m/g)
--no-playlist-folder Download playlist tracks into main directory,
instead of making a playlist subfolder
--onlymp3 Download only the streamable mp3 file,
even if track has a Downloadable file
--onlymp3 Download only mp3 files
--path [path] Use a custom path for downloaded files
--remove Remove any files not downloaded from execution
--sync [file] Compare an archive file to a playlist and downloads/removes any changed tracks
--flac Convert original files to .flac
--sync [file] Compares an archive file to a playlist and downloads/removes any changed tracks
--flac Convert original files to .flac. Only works if the original file is lossless quality
--no-album-tag On some player track get the same cover art if from the same album, this prevent it
--original-art Download original cover art
--original-art Download original cover art, not just 500x500 JPEG
--original-name Do not change name of original file downloads
--no-original Do not download original file; only mp3 or m4a
--original-metadata Do not change metadata of original file downloads
--no-original Do not download original file; only mp3, m4a, or opus
--only-original Only download songs with original file available
--name-format [format] Specify the downloaded file name format
--playlist-name-format [format] Specify the downloaded file name format, if it is being downloaded as part of a playlist
Expand All @@ -88,6 +89,7 @@ scdl me -f
--overwrite Overwrite file if it already exists
--strict-playlist Abort playlist downloading if one track fails to download
--no-playlist Skip downloading playlists
--opus Prefer downloading opus streams over mp3 streams
```


Expand Down
2 changes: 1 addition & 1 deletion scdl/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# -*- encoding: utf-8 -*-
"""Python Soundcloud Music Downloader."""
__version__ = "v2.9.2"
__version__ = "v2.9.3"
51 changes: 25 additions & 26 deletions scdl/scdl.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,15 @@
--opus Prefer downloading opus streams over mp3 streams
"""

import atexit
import base64
import cgi
import configparser
import contextlib
import itertools
import logging
import math
import mimetypes
from typing import Optional, TypedDict
from typing import List, Optional, TypedDict

mimetypes.init()

Expand All @@ -92,16 +92,7 @@
import warnings
from dataclasses import asdict

if os.name == "nt":
import filelock

FileLockTimeout = filelock.Timeout
else:

class FileLockTimeout(Exception):
pass


import filelock
import mutagen
import mutagen.flac
import mutagen.id3
Expand Down Expand Up @@ -148,12 +139,26 @@ class PlaylistInfo(TypedDict):
id: int
title: str

file_lock_dirs: List[pathlib.Path] = []


def clean_up_locks():
for dir in file_lock_dirs:
for lock in dir.glob("*.scdl.lock"):
try:
lock.unlink(True)
except Exception:
pass


atexit.register(clean_up_locks)


def get_filelock(path: pathlib.Path, timeout: int = 10):
if os.name == "nt":
return filelock.FileLock(str(path) + ".scdl.lock", timeout=timeout)
else:
return contextlib.nullcontext()
path = path.resolve()
file_lock_dirs.append(path.parent)
lock_path = str(path) + ".scdl.lock"
return filelock.FileLock(lock_path, timeout=timeout)


def main():
Expand Down Expand Up @@ -712,7 +717,7 @@ def download_original_file(
shutil.move(temp.name, os.path.join(os.getcwd(), filename))
if kwargs.get("flac") and can_convert(filename):
logger.info("Converting to .flac...")
newfilename = limit_filename_length(filename[:-4], ".flac")
newfilename = sanitize_str(filename[:-4], ".flac")

commands = ["ffmpeg", "-i", filename, newfilename, "-loglevel", "error"]
logger.debug(f"Commands: {commands}")
Expand Down Expand Up @@ -760,7 +765,6 @@ def download_hls(

transcoding = None
ext = None

# ordered in terms of preference best -> worst
valid_presets = [("mp3", ".mp3")]

Expand Down Expand Up @@ -836,7 +840,7 @@ def download_track(
# Get user_id from the client
client_user_id = client.get_me().id if client.auth_token else None

lock = get_filelock(f"{track.id}", 0)
lock = get_filelock(pathlib.Path(f"./{track.id}"), 0)

# Downloadable track
downloaded_original = False
Expand All @@ -854,7 +858,7 @@ def download_track(
client, track, title, playlist_info, **kwargs
)
downloaded_original = True
except FileLockTimeout:
except filelock.Timeout:
logger.debug(f"Could not acquire lock: {lock}. Skipping")
return

Expand All @@ -866,7 +870,7 @@ def download_track(
filename, is_already_downloaded = download_hls(
client, track, title, playlist_info, **kwargs
)
except FileLockTimeout:
except filelock.Timeout:
logger.debug(f"Could not acquire lock: {lock}. Skipping")
return

Expand Down Expand Up @@ -1118,11 +1122,6 @@ def set_metadata(
audio.save()


def limit_filename_length(name: str, ext: str, max_bytes=255):
while len(name.encode("utf-8")) + len(ext.encode("utf-8")) > max_bytes:
name = name[:-1]
return name + ext

def is_ffmpeg_available():
"""
Returns true if ffmpeg is available in the operating system
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"clint",
"pathvalidate",
"soundcloud-v2>=1.3.10",
"filelock>=3.0.0; platform_system=='Windows'",
"filelock>=3.0.0",
],
extras_require={"test": ["coveralls", "pytest", "pytest-dotenv", "music-tag"]},
url="https://github.com/flyingrub/scdl",
Expand Down

0 comments on commit a2c4b50

Please sign in to comment.