././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1707436337.8085086 renardo_gatherer-0.1.3/0000755000175100001770000000000014561264462014445 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1707436337.8085086 renardo_gatherer-0.1.3/PKG-INFO0000644000175100001770000000070314561264462015542 0ustar00runnerdockerMetadata-Version: 2.1 Name: renardo_gatherer Version: 0.1.3 Summary: Asset collector for Renardo Python livecoding environment Home-page: http://renardo.org/ Author: Elie Gavoty Author-email: eliegavoty@free.fr License: cc-by-sa-4.0 Description-Content-Type: text/markdown Requires-Dist: requests Requires-Dist: beautifulsoup4 Requires-Dist: indexed Asset collector (samples packs, synthdefs, etc) for Renardo Python livecoding environment ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1707436337.8085086 renardo_gatherer-0.1.3/renardo_gatherer/0000755000175100001770000000000014561264462017760 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1707436328.0 renardo_gatherer-0.1.3/renardo_gatherer/__init__.py0000644000175100001770000000077514561264450022077 0ustar00runnerdockerimport os from renardo_gatherer.config_dir import SAMPLES_DIR_PATH from renardo_gatherer.samples_download import DEFAULT_SAMPLES_PACK_NAME def get_samples_dir_path(): return SAMPLES_DIR_PATH def main(): pass # def get_spack_dirname_from_num(spack_num): # '''associate samples pack directory names in sample folder with pack numbers''' # samples_pack_dirname = ('foxdot_default' if str(spack_num) == '0' # else str(spack_num)) # return samples_pack_dirname ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1707436328.0 renardo_gatherer-0.1.3/renardo_gatherer/config_dir.py0000644000175100001770000000127114561264450022433 0ustar00runnerdockerimport os import pathlib from sys import platform SAMPLES_DIR_PATH = None # default config path # on windows AppData/Roaming/renardo # on Linux ~/.config/renardo # on MacOS /Users//Library/Application Support/renardo if platform == "linux" or platform == "linux2" : home_path = pathlib.Path.home() SAMPLES_DIR_PATH = home_path / '.config' / 'renardo' / 'samples' elif platform == "darwin": home_path = pathlib.Path.home() SAMPLES_DIR_PATH = home_path / 'Library' / 'Application Support' / 'renardo' / 'samples' elif platform == "win32": appdata_roaming_path = pathlib.Path(os.getenv('APPDATA')) SAMPLES_DIR_PATH = appdata_roaming_path / 'renardo' / 'samples' ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1707436328.0 renardo_gatherer-0.1.3/renardo_gatherer/samples_download.py0000644000175100001770000001554114561264450023670 0ustar00runnerdockerimport os from datetime import datetime from indexed import IndexedOrderedDict import requests from bs4 import BeautifulSoup from renardo_gatherer.config_dir import SAMPLES_DIR_PATH SAMPLES_DOWNLOAD_SERVER = 'https://samples.renardo.org' DEFAULT_SAMPLES_PACK_NAME = '0_foxdot_default' LOOP_SUBDIR = '_loop_' class SampleDownloadError(Exception): pass nonalpha = {"&" : "ampersand", "*" : "asterix", "@" : "at", "\\" : "backslash", "|" : "bar", "^" : "caret", ":" : "colon", "$" : "dollar", "=" : "equals", "!" : "exclamation", "/" : "forwardslash", "#" : "hash", "-" : "hyphen", "<" : "lessthan", "%" : "percent", "+" : "plus", "?" : "question", ";" : "semicolon", "~" : "tilde", "1" : "1", "2" : "2", "3" : "3", "4" : "4" } class SPack: '''Type Samples Pack to describe this resource and avoid string -> pattern conversion in Player''' def __init__(self, name): self.name = name self.path = SAMPLES_DIR_PATH / name self.loop_path = self.path / LOOP_SUBDIR def sample_path_from_symbol(self, symbol): """ Return the sample search directory for a symbol """ sample_path = None if symbol.isalpha(): low_up_dirname = 'upper' if symbol.isupper() else 'lower' sample_path = self.path / symbol.lower() / low_up_dirname elif symbol in nonalpha: longname = nonalpha[symbol] sample_path = self.path / '_' / longname return sample_path def download_finished(self): return (self.path / "downloaded_at.txt").exists() def download_file(self, audiofile_relative_path, logger=None): url = f'{SAMPLES_DOWNLOAD_SERVER}/{self.name}/' + audiofile_relative_path response = requests.get(url) if logger: logger.write_line(url) else: print(url) if response.status_code != 200: raise SampleDownloadError if "content-disposition" in response.headers: content_disposition = response.headers["content-disposition"] filename_full = content_disposition.split("filename=")[1] filename = filename_full.split("/")[-1] else: filename = url.split("/")[-1] with open(self.path / audiofile_relative_path, mode="wb") as file: file.write(response.content) if logger: logger.write_line(f"Downloaded file {filename}") else: print(f"Downloaded file {filename}") class SPackManager: def __init__(self): self.logger = None self._samples_packs = IndexedOrderedDict() # usefull to access from key OR index directly # Workaround to rename the folder temporarily if (SAMPLES_DIR_PATH / 'foxdot_default').exists() and not (SAMPLES_DIR_PATH/DEFAULT_SAMPLES_PACK_NAME).exists(): (SAMPLES_DIR_PATH / 'foxdot_default').rename(SAMPLES_DIR_PATH / DEFAULT_SAMPLES_PACK_NAME) #self.init_default_spack() SPackManager.ensure_renardo_samples_directory() self.scan_existing_samples_pack() @staticmethod def ensure_renardo_samples_directory(): if not SAMPLES_DIR_PATH.exists(): SAMPLES_DIR_PATH.mkdir(parents=True, exist_ok=True) def init_default_spack(self): if not SPackManager.is_default_spack_initialized(): self.download_samples_pack(samples_pack_name=DEFAULT_SAMPLES_PACK_NAME) else: self.add_samples_pack(SPack(DEFAULT_SAMPLES_PACK_NAME)) def set_logger(self, logger): self.logger = logger @staticmethod def is_default_spack_initialized(): return (SAMPLES_DIR_PATH / DEFAULT_SAMPLES_PACK_NAME / 'downloaded_at.txt').exists() def default_spack(self): return self.get_spack(0) def scan_existing_samples_pack(self): if SPackManager.is_default_spack_initialized(): self.add_samples_pack(SPack(DEFAULT_SAMPLES_PACK_NAME)) for directory in [f for f in SAMPLES_DIR_PATH.iterdir() if f.is_dir() and f.name != DEFAULT_SAMPLES_PACK_NAME]: self.add_samples_pack(SPack(directory.name)) def add_samples_pack(self, samples_pack: SPack): self._samples_packs[samples_pack.name] = samples_pack return samples_pack def get_spack(self, num_or_spack) -> SPack: return ( self._samples_packs.values()[num_or_spack] if isinstance(num_or_spack, int) else self._samples_packs[SPack.__name__] ) def download_samples_pack(self, samples_pack_name): # if download fails sample pack + folder exists but without downloaded_at.txt file samples_pack = self.add_samples_pack(SPack(samples_pack_name)) base_url = f"{SAMPLES_DOWNLOAD_SERVER}/{samples_pack.name}/" directory_links = [] audiofile_links = [] if self.logger: self.logger.write_line("Scanning samples pack...") else: print("Scanning samples pack...") self.find_audio_links_recursive(base_url, directory_links, audiofile_links) # print(audiofile_links) for subdir in directory_links: (SAMPLES_DIR_PATH / samples_pack_name / subdir).mkdir(parents=True, exist_ok=True) for audiofile in audiofile_links: samples_pack.download_file(audiofile, self.logger) with open(SAMPLES_DIR_PATH / samples_pack_name / 'downloaded_at.txt', mode="w") as file: file.write(str(datetime.now())) def link_is_directory(self, url): return url.endswith('/') def find_audio_links_recursive(self, base_url, directory_links, audiofile_links, current_path=''): page = requests.get(base_url+current_path).content bsObj = BeautifulSoup(page, 'html.parser') maybe_directories = bsObj.findAll('a', href=True) for link in maybe_directories: # print(f"link : {link['href']}") # print(link_is_directory(link['href'])) if self.link_is_directory(link['href']) and link["href"] != '../': new_path = current_path + link['href'] directory_links.append(new_path) self.find_audio_links_recursive(base_url, directory_links, audiofile_links, current_path=new_path) else: if( link['href'].endswith('.wav') or link['href'].endswith('.WAV') or link['href'].endswith('.aiff') or link['href'].endswith('.aif') or link['href'].endswith('.AIF') or link['href'].endswith('.AIFF') ): # print(link['href']) audiofile_links.append(current_path + link['href']) ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1707436337.8085086 renardo_gatherer-0.1.3/renardo_gatherer.egg-info/0000755000175100001770000000000014561264462021452 5ustar00runnerdocker././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1707436337.0 renardo_gatherer-0.1.3/renardo_gatherer.egg-info/PKG-INFO0000644000175100001770000000070314561264461022546 0ustar00runnerdockerMetadata-Version: 2.1 Name: renardo_gatherer Version: 0.1.3 Summary: Asset collector for Renardo Python livecoding environment Home-page: http://renardo.org/ Author: Elie Gavoty Author-email: eliegavoty@free.fr License: cc-by-sa-4.0 Description-Content-Type: text/markdown Requires-Dist: requests Requires-Dist: beautifulsoup4 Requires-Dist: indexed Asset collector (samples packs, synthdefs, etc) for Renardo Python livecoding environment ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1707436337.0 renardo_gatherer-0.1.3/renardo_gatherer.egg-info/SOURCES.txt0000644000175100001770000000053314561264461023336 0ustar00runnerdockersetup.py renardo_gatherer/__init__.py renardo_gatherer/config_dir.py renardo_gatherer/samples_download.py renardo_gatherer.egg-info/PKG-INFO renardo_gatherer.egg-info/SOURCES.txt renardo_gatherer.egg-info/dependency_links.txt renardo_gatherer.egg-info/entry_points.txt renardo_gatherer.egg-info/requires.txt renardo_gatherer.egg-info/top_level.txt././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1707436337.0 renardo_gatherer-0.1.3/renardo_gatherer.egg-info/dependency_links.txt0000644000175100001770000000000114561264461025517 0ustar00runnerdocker ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1707436337.0 renardo_gatherer-0.1.3/renardo_gatherer.egg-info/entry_points.txt0000644000175100001770000000007314561264461024747 0ustar00runnerdocker[console_scripts] renardo_gatherer = renardo_gatherer:main ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1707436337.0 renardo_gatherer-0.1.3/renardo_gatherer.egg-info/requires.txt0000644000175100001770000000004014561264461024043 0ustar00runnerdockerrequests beautifulsoup4 indexed ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1707436337.0 renardo_gatherer-0.1.3/renardo_gatherer.egg-info/top_level.txt0000644000175100001770000000002114561264461024174 0ustar00runnerdockerrenardo_gatherer ././@PaxHeader0000000000000000000000000000003400000000000010212 xustar0028 mtime=1707436337.8085086 renardo_gatherer-0.1.3/setup.cfg0000644000175100001770000000004614561264462016266 0ustar00runnerdocker[egg_info] tag_build = tag_date = 0 ././@PaxHeader0000000000000000000000000000002600000000000010213 xustar0022 mtime=1707436328.0 renardo_gatherer-0.1.3/setup.py0000644000175100001770000000136414561264450016160 0ustar00runnerdocker#!/usr/bin/env python from setuptools import setup setup( name='renardo_gatherer', version="0.1.3", description='Asset collector for Renardo Python livecoding environment', long_description=""" Asset collector (samples packs, synthdefs, etc) for Renardo Python livecoding environment """, long_description_content_type="text/markdown", author='Elie Gavoty', author_email='eliegavoty@free.fr', license='cc-by-sa-4.0', url='http://renardo.org/', packages=[ 'renardo_gatherer', ], install_requires=[ 'requests', 'beautifulsoup4', 'indexed', ], entry_points={ 'console_scripts': [ 'renardo_gatherer = renardo_gatherer:main', ] } )